.NET程序员项目开发必知必会—Dev环境中的集成测试用例执行时上下文环境检查(实战)

简介:

Microsoft.NET 解决方案,项目开发必知必会。

从这篇文章开始我将分享一系列我认为在实际工作中很有必要的一些.NET项目开发的核心技术点,所以我称为必知必会。尽管这一些列是使用.NET/C#来展现,但是同样适用于其他类似的OO技术平台,这些技术点可能称不上完整的技术,但是它是经验的总结,是掉过多少坑之后的觉醒,所以有必要花几分钟时间记住它,在真实的项目开发中你就知道是多么的有帮助。好了,废话不说了,进入主题。

我们在开发服务时为了调试方便会在本地进行一个基本的模块测试,你也可以认为是集成测试,只不过你的测试用例不会覆盖到80%以上,而是一些我们认为在开发时不是很放心的点才会编写适当的用例来测试它。

集成测试用例通常有多个执行上下文,对于我们开发人员来说我们的执行上下文通常都在本地,测试人员的上下文在测试环境中。开发人员的测试用来是不能够连接到其他环境中去的(当然视具体情况而定,有些用例很危险是不能够乱连接的,本文会讲如何解决),开发人员运行的集成测试用例所要访问的所有资源、服务都是在开发环境中的。这里依然存在但是,但是为了调试方便,我们还是需要能够在必要的时候连接到其他环境中去调试问题,为了能够真实的模拟出问题的环境、可真实的数据,我们需要能有一个这样的机制,在需要的时候我能够打开某个设置让其能够切换集成测试运行的环境上下文,其实说白了就是你所要连接的环境、数据源的连接地址。

本篇文章我们将通过一个简单的实例来了解如何简单的处理这中情况,这其实基于对测试用来不断重构后的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using  System;
using  Microsoft.VisualStudio.TestTools.UnitTesting; 
 
namespace  OrderManager.Test
{
     using  ProductService.Contract; 
 
     /// <summary>
     /// Product service integration tests.
     /// </summary>
     [TestClass]
     public  class  ProductServiceIntegrationTest
     {
         /// <summary>
         /// service address.
         /// </summary>
         public  const  string  ServiceAddress =  "http://dev.service.ProductService/"
 
         /// <summary>
         /// Product service get product by pid test.
         /// </summary>
         [TestMethod]
         public  void  ProductService_GetProductByPid_Test()
         {
             var  serviceInstance = ProductServiceClient.CreateClient(ServiceAddress);
             var  testResult = serviceInstance.GetProductByPid(0393844); 
 
             Assert.AreNotEqual(testResult,  null );
             Assert.AreEqual(testResult.Pid, 0393844);
         }
     }
}

这是一个实际的集成测试用例代码,有一个当前测试类共用的服务地址,这个地址是DEV环境的,当然你也可以定义其他几个环境的服务地址,前提是环境是允许你连接的,那才有实际意义。

我们来看测试用例,它是一个查询方法测试用例,用来对ProductServiceClient.GetProductByPid服务方法进行测试,由于面向查询的操作是等幕的,不论我们查询多少次这个ID的Product,都不会对数据造成影响,但是如果我们测试的是一个更新或者删除就会带来问题。

在DEV环境中,测试更新、删除用例没有问题,但是如果你的机器是能够连接到远程某个生产或者PRD测试上时会带来一定的危险性,特别是在忙的时候,加班加点的干进度,你很难记住你当前的机器的host配置中是否还连接着远程的生产机器上,或者根本就不需要配置host就能够连接到某个你不应该连接的环境上。

这是目前的问题,那么我们如何解决这个问题呢 ,我们通过对测试代码进行一个简单的重构就可以避免由于连接到不该连接的环境中运行危险的测试用例。

其实很多时候,重构真的能够帮助我们找到出口,就好比俗话说的:"出口就在转角处“,只有不断重构才能够逐渐的保证项目的质量,而这种效果是很难得的。

提取抽象基类,对测试要访问的环境进行明确的定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace  OrderManager.Test
{
     public  abstract  class  ProductServiceIntegrationBase
     {
         /// <summary>
         /// service address.
         /// </summary>
         protected  const  string  ServiceAddressForDev =  "http://dev.service.ProductService/"
 
         /// <summary>
         /// service address.
         /// </summary>
         protected  const  string  ServiceAddressForPrd =  "http://Prd.service.ProductService/"
 
         /// <summary>
         /// service address.
         /// </summary>
         protected  const  string  ServiceAddressTest =  "http://Test.service.ProductService/" ;
     }
}

对具体的测试类消除重复代码,加入统一的构造方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
using  System;
using  Microsoft.VisualStudio.TestTools.UnitTesting; 
 
namespace  OrderManager.Test
{
     using  ProductService.Contract; 
 
     /// <summary>
     /// Product service integration tests.
     /// </summary>
     [TestClass]
     public  class  ProductServiceIntegrationTest : ProductServiceIntegrationBase
     {
         /// <summary>
         /// product service client.
         /// </summary>
         private  ProductServiceClient serviceInstance; 
 
         /// <summary>
         /// Initialization test instance.
         /// </summary>
         [TestInitialize]
         public  void  InitTestInstance()
         {
             serviceInstance = ProductServiceClient.CreateClient(ServiceAddressForDev /*for dev*/ );
        
 
         /// <summary>
         /// Product service get product by pid test.
         /// </summary>
         [TestMethod]
         public  void  ProductService_GetProductByPid_Test()
         {
             var  testResult = serviceInstance.GetProductByPid(0393844); 
 
             Assert.AreNotEqual(testResult,  null );
             Assert.AreEqual(testResult.Pid, 0393844);
        
 
         /// <summary>
         /// Product service delete search index test.
         /// </summary>
         [TestMethod]
         public  void  ProductService_DeleteProductSearchIndex_Test()
         {
             var  testResult = serviceInstance.DeleteProductSearchIndex(); 
 
             Assert.IsTrue(testResult);
         }
     }
}

消除重复代码后,我们需要加入对具体测试用例检查是否能够连接到某个环境中去。我加入了一个DeleteProductSearchIndex测试用例,该用例是用来测试删除搜索索引的,这个测试用例只能够在本地DEV环境中运行(你可能觉得这个删除接口不应该放在这个服务里,这里只是举一个例子,无需纠结)。

为了能够有一个检查机制能提醒开发人员你目前连接的地址是哪一个,我们需要借助于测试上下文。

重构后,我们看一下现在的测试代码结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using  System;
using  Microsoft.VisualStudio.TestTools.UnitTesting; 
 
namespace  OrderManager.Test
{
     using  ProductService.Contract; 
 
     /// <summary>
     /// Product service integration tests.
     /// </summary>
     [TestClass]
     public  class  ProductServiceIntegrationTest : ProductServiceIntegrationBase
     {
         /// <summary>
         /// product service client.
         /// </summary>
         private  ProductServiceClient serviceInstance; 
 
         /// <summary>
         /// Initialization test instance.
         /// </summary>
         [TestInitialize]
         public  void  InitTestInstance()
         {
             serviceInstance = ProductServiceClient.CreateClient(ServiceAddressForPrd /*for dev*/ ); 
 
             this .CheckCurrentTestCaseIsRun( this .serviceInstance); //check current test case .
        
 
         /// <summary>
         /// Product service get product by pid test.
         /// </summary>
         [TestMethod]
         public  void  ProductService_GetProductByPid_Test()
         {
             var  testResult = serviceInstance.GetProductByPid(0393844); 
 
             Assert.AreNotEqual(testResult,  null );
             Assert.AreEqual(testResult.Pid, 0393844);
        
 
         /// <summary>
         /// Product service delete search index test.
         /// </summary>
         [TestMethod]
         public  void  ProductService_DeleteProductSearchIndex_Test()
         {
             var  testResult = serviceInstance.DeleteProductSearchIndex(); 
 
             Assert.IsTrue(testResult);
         }
     }
}

我们加入了一个很重要的测试实例运行时方法InitTestInstance,该方法会在测试用例每次实例化时先执行,在方法内部有一个用来检查当前测试用例运行的环境 
this.CheckCurrentTestCaseIsRun(this.serviceInstance);//check current test case .,我们转到基类中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
using  System;
using  Microsoft.VisualStudio.TestTools.UnitTesting; 
 
namespace  OrderManager.Test
{
     public  abstract  class  ProductServiceIntegrationBase
     {
         /// <summary>
         /// service address.
         /// </summary>
         protected  const  string  ServiceAddressForDev =  "http://dev.service.ProductService/" ;
 
         /// <summary>
         /// get service address.
         /// </summary>
         protected  const  string  ServiceAddressForPrd =  "http://Prd.service.ProductService/" ;
 
         /// <summary>
         /// service address.
         /// </summary>
         protected  const  string  ServiceAddressTest =  "http://Test.service.ProductService/" ;
 
         /// <summary>
         /// Test context .
         /// </summary>
         public  TestContext TestContext {  get set ; } 
 
         /// <summary>
         /// is check is run for current test case.
         /// </summary>
         protected  void  CheckCurrentTestCaseIsRun(ProductService.Contract.ProductServiceClient testObject)
         {
             if  (testObject.ServiceAddress.Equals(ServiceAddressForPrd)) // Prd 环境,需要小心检查
             {
                 if  ( this .TestContext.TestName.Equals( "ProductService_DeleteProductSearchIndex_Test" ))
                     Assert.IsTrue( false "当前测试用例连接的环境为PRD,请停止当前用例的运行。" );
             }
             else  if  (testObject.ServiceAddress.Equals(ServiceAddressTest)) //Test 环境,检查约定几个用例
             {
                 if  ( this .TestContext.TestName.Equals( "ProductService_DeleteProductSearchIndex_Test" ))
                     Assert.IsTrue( false "当前测试用例连接的环境为TEST,为了不破坏TEST环境,请停止用例的运行。" );
             }
         }
     }
     
}

在检查方法中我们使用简单的判断某个用例不能够在PRD、TEST环境下执行,虽然判断有点简单,但是在真实的项目中足够了,简单有时候是一种设计思想。我们运行所有的测试用例,查看各个状态。

wKioL1QW2cOyd87PAAIr1ZdLOvg782.jpg

一目了然,更为重要的是它不会影响你对其他用例的执行。当你在深夜12点排查问题的时候,你很难控制自己的眼花、体虚导致的用例执行错误带来的大问题,甚至是无法挽回的的错误。

此文献给那些跟我一样的.NET程序员们,通过简单的重构,我们放开了自己。




 本文转自 王清培 51CTO博客,原文链接:http://blog.51cto.com/wangqingpei557/1553012,如需转载请自行联系原作者





相关文章
|
16天前
|
分布式计算 大数据 Apache
ClickHouse与大数据生态集成:Spark & Flink 实战
【10月更文挑战第26天】在当今这个数据爆炸的时代,能够高效地处理和分析海量数据成为了企业和组织提升竞争力的关键。作为一款高性能的列式数据库系统,ClickHouse 在大数据分析领域展现出了卓越的能力。然而,为了充分利用ClickHouse的优势,将其与现有的大数据处理框架(如Apache Spark和Apache Flink)进行集成变得尤为重要。本文将从我个人的角度出发,探讨如何通过这些技术的结合,实现对大规模数据的实时处理和分析。
48 2
ClickHouse与大数据生态集成:Spark & Flink 实战
|
2月前
|
数据采集 运维 测试技术
软件测试之道 -- 做一个有匠心的程序员!
作者一年前围绕设计模式与代码重构写了一篇《代码整洁之道 -- 告别码农,做一个有思想的程序员!》的文章。本文作为续篇,从测试角度谈程序员对软件质量的追求。
|
30天前
|
Dart Android开发
鸿蒙Flutter实战:03-鸿蒙Flutter开发中集成Webview
本文介绍了在OpenHarmony平台上集成WebView的两种方法:一是使用第三方库`flutter_inappwebview`,通过配置pubspec.lock文件实现;二是编写原生ArkTS代码,自定义PlatformView,涉及创建入口能力、注册视图工厂、处理方法调用及页面构建等步骤。
48 0
|
2月前
|
监控 关系型数据库 MySQL
zabbix agent集成percona监控MySQL的插件实战案例
这篇文章是关于如何使用Percona监控插件集成Zabbix agent来监控MySQL的实战案例。
53 2
zabbix agent集成percona监控MySQL的插件实战案例
|
3月前
|
前端开发 关系型数据库 测试技术
django集成pytest进行自动化单元测试实战
在Django项目中集成Pytest进行单元测试可以提高测试的灵活性和效率,相比于Django自带的测试框架,Pytest提供了更为丰富和强大的测试功能。本文通过一个实际项目ishareblog介绍django集成pytest进行自动化单元测试实战。
49 3
django集成pytest进行自动化单元测试实战
|
3月前
|
机器学习/深度学习 存储 前端开发
实战揭秘:如何借助TensorFlow.js的强大力量,轻松将高效能的机器学习模型无缝集成到Web浏览器中,从而打造智能化的前端应用并优化用户体验
【8月更文挑战第31天】将机器学习模型集成到Web应用中,可让用户在浏览器内体验智能化功能。TensorFlow.js作为在客户端浏览器中运行的库,提供了强大支持。本文通过问答形式详细介绍如何使用TensorFlow.js将机器学习模型带入Web浏览器,并通过具体示例代码展示最佳实践。首先,需在HTML文件中引入TensorFlow.js库;接着,可通过加载预训练模型如MobileNet实现图像分类;然后,编写代码处理图像识别并显示结果;此外,还介绍了如何训练自定义模型及优化模型性能的方法,包括模型量化、剪枝和压缩等。
50 1
|
6月前
|
JSON API 数据处理
【Swift开发专栏】Swift中的RESTful API集成实战
【4月更文挑战第30天】本文探讨了在Swift中集成RESTful API的方法,涉及RESTful API的基础概念,如HTTP方法和设计原则,以及Swift的网络请求技术,如`URLSession`、`Alamofire`和`SwiftyJSON`。此外,还强调了数据处理、错误管理和异步操作的重要性。通过合理利用这些工具和策略,开发者能实现高效、稳定的API集成,提升应用性能和用户体验。
126 0
|
3月前
|
JSON 数据管理 关系型数据库
【Dataphin V3.9】颠覆你的数据管理体验!API数据源接入与集成优化,如何让企业轻松驾驭海量异构数据,实现数据价值最大化?全面解析、实战案例、专业指导,带你解锁数据整合新技能!
【8月更文挑战第15天】随着大数据技术的发展,企业对数据处理的需求不断增长。Dataphin V3.9 版本提供更灵活的数据源接入和高效 API 集成能力,支持 MySQL、Oracle、Hive 等多种数据源,增强 RESTful 和 SOAP API 支持,简化外部数据服务集成。例如,可轻松从 RESTful API 获取销售数据并存储分析。此外,Dataphin V3.9 还提供数据同步工具和丰富的数据治理功能,确保数据质量和一致性,助力企业最大化数据价值。
169 1
|
3月前
|
jenkins Java 持续交付
【一键搞定!】Jenkins 自动发布 Java 代码的神奇之旅 —— 从零到英雄的持续集成/部署实战秘籍!
【8月更文挑战第9天】随着软件开发自动化的发展,持续集成(CI)与持续部署(CD)已成为现代流程的核心。Jenkins 作为一款灵活且功能丰富的开源 CI/CD 工具,在业界应用广泛。以一家电商公司的 Java 后端服务为例,通过搭建 Jenkins 自动化发布流程,包括创建 Jenkins 项目、配置 Git 仓库、设置构建触发器以及编写构建脚本等步骤,可以实现代码的快速可靠部署。
136 2
|
3月前
|
C# Windows 开发者
当WPF遇见OpenGL:一场关于如何在Windows Presentation Foundation中融入高性能跨平台图形处理技术的精彩碰撞——详解集成步骤与实战代码示例
【8月更文挑战第31天】本文详细介绍了如何在Windows Presentation Foundation (WPF) 中集成OpenGL,以实现高性能的跨平台图形处理。通过具体示例代码,展示了使用SharpGL库在WPF应用中创建并渲染OpenGL图形的过程,包括开发环境搭建、OpenGL渲染窗口创建及控件集成等关键步骤,帮助开发者更好地理解和应用OpenGL技术。
242 0