如何使用指定测试类型的选项执行自动化测试
How do I execute an automated test with the option of specifying test type
如何执行自动化测试并选择将其指定为单元测试或"light-weight integration test"而不编写相同的测试两次并且仅更改它所依赖的接口使其成为两者之一?
具体来说,我想执行一个测试并将其指定为单元测试或集成测试。
根据我选择的模式,测试应该会生成服务接口。
- 我不想维护两套相同的代码,唯一的区别是一个接口:
- 外接服务(集成测试)
- MockService(单元测试)
示例:
Construct testable business layer logic
进行形态测试没有意义。
单元测试测试单段代码是否工作孤立。
集成测试测试您的代码在集成到更大的代码库时是否正常工作
例如,用于对视图模型进行单元测试的验收标准和伪代码:
public TestMeViewModelTests {
public when_adding_a_warehouse_then_should_call_service_AddNewWarehouse_given_WarehouseModel {
//Arrange
var warehouseViewModel = new WarehouseViewModel { id=1 };
var service = new Mock<IService>();
var interfaceViewModel = new TestMeViewModel(service.Object);
//Act
interfaceViewModel.AddWarehouseCommand(warehouseViewModel);
//Assert
service.Verify(s=>s.AddNewWarehouse(wareHouseViewModel), Times.Once);
}
}
看,没有交叉授粉的问题。您只是在测试添加新仓库时是否调用幂等操作。如果您使用的是 ORM,那么您还需要单元测试来验证数据服务调用是否正在发生。
如果您要进行集成测试,那么您的测试项目将指向反映生产环境的 "WarehouseTest" 连接字符串,并且您的集成测试可能会执行相同的逻辑,但随后进行检查以确保测试插入的仓库实际上在测试结束时在您的数据库中。
好的,我想我明白现在发生了什么。
您希望能够在运行时间更改接口的实现,以便更改单元测试 运行 的位置。
在那种情况下,您需要某种抽象工厂模式。
示例:
public class ViewModel {
IService _service;
public ViewModel(IServiceFactory factory){
_service = factory.Create();
}
public void SaveWarehouse(Warehouse aWarehouse) {
_service.AddWarehouse(aWarehouse);
}
}
public interface IServiceFactory {
IService Create();
}
public class ProductionFactory : IServiceFactory { //Dependency injected
public IService Create() {
return new ProdService();
}
}
单元测试:
public class ViewModelTest {
public void when_adding_warehouse() {
//Arrange
var aWarehouse = new WarehouseViewModel { id=1 };
var serviceFactory = new Mock<IServiceFactory>().Object);
var service = new Mock<IService>();
serviceFactory.Setup(factory => factory.Create()).Returns(service.Object);
var viewModel = new ViewModel(serviceFactory.Object);
//Act
viewModel.AddWarehouseCommand(warehouseViewModel);
//Assert
service.Verify(s=>s.AddNewWarehouse(aWarehouse), Times.Once);
}
}
集成测试:
您的集成测试将包括本地内部 IService 实现和返回本地 IService 实现的本地内部 IServiceFactory 实现。您的所有测试都将 运行 完美无缺,并且您可以非常轻松地控制数据的去向。
向应用程序配置添加条目。
应用程序配置:
<appSettings>
<add key="IsUnitTest" value="True" />
</appSettings>
然后从配置文件中获取 key/value 对,并根据配置值设置您的服务依赖性。
测试
[TestClass]
public class MyTest
{
IServices _service = null;
[TestInitialize]
public void Setup()
{
var isUnitTest = bool.Parse(ConfigurationManager.AppSettings["IsUnitTest"]);
if (isUnitTest)
{
_service = new MockService();
}
else
{
_service = new Service();
}
}
。
.
.
我不同意 C Bauer。这里根本没有共识。模拟和依赖注入对解决这个问题大有帮助。在过去的几年里,我看到这种方法被更频繁地使用,而且效果很好。
通常在角色跨职能的敏捷环境中。一些团队希望使用单个代码 base/solution。特别是在代码库规模相对较小的情况下,"unit" 测试能够作为轻量级集成测试工作得很好。这里没有黑白解决方案,只有最适合手头问题的解决方案。不管其他人怎么说,有多种方法可以解决这个问题,而且 solutions/approaches 一直在增长和变化。
如何执行自动化测试并选择将其指定为单元测试或"light-weight integration test"而不编写相同的测试两次并且仅更改它所依赖的接口使其成为两者之一?
具体来说,我想执行一个测试并将其指定为单元测试或集成测试。 根据我选择的模式,测试应该会生成服务接口。
- 我不想维护两套相同的代码,唯一的区别是一个接口:
- 外接服务(集成测试)
- MockService(单元测试)
示例: Construct testable business layer logic
进行形态测试没有意义。
单元测试测试单段代码是否工作孤立。
集成测试测试您的代码在集成到更大的代码库时是否正常工作
例如,用于对视图模型进行单元测试的验收标准和伪代码:
public TestMeViewModelTests {
public when_adding_a_warehouse_then_should_call_service_AddNewWarehouse_given_WarehouseModel {
//Arrange
var warehouseViewModel = new WarehouseViewModel { id=1 };
var service = new Mock<IService>();
var interfaceViewModel = new TestMeViewModel(service.Object);
//Act
interfaceViewModel.AddWarehouseCommand(warehouseViewModel);
//Assert
service.Verify(s=>s.AddNewWarehouse(wareHouseViewModel), Times.Once);
}
}
看,没有交叉授粉的问题。您只是在测试添加新仓库时是否调用幂等操作。如果您使用的是 ORM,那么您还需要单元测试来验证数据服务调用是否正在发生。
如果您要进行集成测试,那么您的测试项目将指向反映生产环境的 "WarehouseTest" 连接字符串,并且您的集成测试可能会执行相同的逻辑,但随后进行检查以确保测试插入的仓库实际上在测试结束时在您的数据库中。
好的,我想我明白现在发生了什么。
您希望能够在运行时间更改接口的实现,以便更改单元测试 运行 的位置。
在那种情况下,您需要某种抽象工厂模式。
示例:
public class ViewModel {
IService _service;
public ViewModel(IServiceFactory factory){
_service = factory.Create();
}
public void SaveWarehouse(Warehouse aWarehouse) {
_service.AddWarehouse(aWarehouse);
}
}
public interface IServiceFactory {
IService Create();
}
public class ProductionFactory : IServiceFactory { //Dependency injected
public IService Create() {
return new ProdService();
}
}
单元测试:
public class ViewModelTest {
public void when_adding_warehouse() {
//Arrange
var aWarehouse = new WarehouseViewModel { id=1 };
var serviceFactory = new Mock<IServiceFactory>().Object);
var service = new Mock<IService>();
serviceFactory.Setup(factory => factory.Create()).Returns(service.Object);
var viewModel = new ViewModel(serviceFactory.Object);
//Act
viewModel.AddWarehouseCommand(warehouseViewModel);
//Assert
service.Verify(s=>s.AddNewWarehouse(aWarehouse), Times.Once);
}
}
集成测试:
您的集成测试将包括本地内部 IService 实现和返回本地 IService 实现的本地内部 IServiceFactory 实现。您的所有测试都将 运行 完美无缺,并且您可以非常轻松地控制数据的去向。
向应用程序配置添加条目。
应用程序配置:
<appSettings>
<add key="IsUnitTest" value="True" />
</appSettings>
然后从配置文件中获取 key/value 对,并根据配置值设置您的服务依赖性。
测试
[TestClass]
public class MyTest
{
IServices _service = null;
[TestInitialize]
public void Setup()
{
var isUnitTest = bool.Parse(ConfigurationManager.AppSettings["IsUnitTest"]);
if (isUnitTest)
{
_service = new MockService();
}
else
{
_service = new Service();
}
}
。 . .
我不同意 C Bauer。这里根本没有共识。模拟和依赖注入对解决这个问题大有帮助。在过去的几年里,我看到这种方法被更频繁地使用,而且效果很好。
通常在角色跨职能的敏捷环境中。一些团队希望使用单个代码 base/solution。特别是在代码库规模相对较小的情况下,"unit" 测试能够作为轻量级集成测试工作得很好。这里没有黑白解决方案,只有最适合手头问题的解决方案。不管其他人怎么说,有多种方法可以解决这个问题,而且 solutions/approaches 一直在增长和变化。