TestNG进行接口测试,脚本及可维护性框架

注: 以下内容引自http://blog.csdn.net/u010321474/article/details/49977969

TestNG进行接口测试,脚本及可维护性框架

原创 2015年11月22日 15:10:30
  • testng被普遍使用于基于java和spring的系统结构中,用于保证系统功能,本身testng的特点

    1.结构清晰

2.支持多种数据源

3.可与maven集成

4.环境/数据准备方便

可用于系统中对外提供的接口进行接口测试脚本的编写(单元测试则一般用junit完成)。

经典的测试脚本,一般分为三个步骤:

1.数据和环境初始化;

2.执行被测接口调用;

3.断言判断。

负责任和健壮的测试脚本,一般还要进行测试数据初始化,测试依赖的环境的调整(如业务开关打开),在执行完测试脚本后,进行数据的清理,如环境的恢复和测试遗留数据的清理。

下面记录一个简单的接口测试编写过程:

被测接口:

[java] view plain copy
  
 1 package net.test.testng.service;  
 2   
 3 /** 
 4  * interface to be tested. 
 5  * @author T0DD 
 6  * 
 7  */  
 8 public interface ToBeTestedService {  
 9     /** 
10      * return a string. 
11      * @return  
12      */  
13     public String returnString();  
14       
15     /** 
16      * return a obj 
17      * @return 
18      */  
19     public Object returnObject();  
20   
21 }

被测接口实现:
[java] view plain copy
   
 1 package net.test.testng.service.impl;  
 2   
 3 import java.sql.SQLException;  
 4   
 5 import net.test.testng.model.Result;  
 6 import net.test.testng.service.DataBaseDAO;  
 7 import net.test.testng.service.FunctionSwitch;  
 8 import net.test.testng.service.ToBeTestedService;  
 9   
10 public class ToBeTestedServicezImpl implements ToBeTestedService {  
11   
12     protected DataBaseDAO dataBaseDAO;  
13   
14     protected FunctionSwitch functionSwitch;  
15   
16     @Override  
17     public String returnString() {  
18         return "a string";  
19     }  
20   
21     @Override  
22     public Object returnObject() {  
23   
24         functionSwitch.setAvaiable(true);  
25   
26         Object queriedData = null;  
27         try {  
28             queriedData = dataBaseDAO.readData("select * from test db;");  
29         } catch (SQLException e) {  
30             return new Result(false, "DB error.", null);  
31         }  
32   
33         return new Result(true, "Switch turned on and queried successed.",  
34                 queriedData);  
35     }  
36   
37 }  
  
其中两个方法,一个非常简单的方法,returnString,只返回一个“a string";另一个,根据业务开关代开与否,进行数据库的读操作,组装result对象返回,result定义为:
[java] view plain copy
  
 1 package net.test.testng.model;  
 2   
 3 public class Result {  
 4   
 5     public boolean isSuccess;  
 6   
 7     public String errorMsg;  
 8   
 9     public String succesMsg;  
10   
11     public Object data;  
12   
13     public Result(boolean isSuccess, String msg, Object data) {  
14         super();  
15         this.isSuccess = isSuccess;  
16         if (isSuccess) {  
17             this.succesMsg = msg;  
18         } else {  
19             this.errorMsg = msg;  
20         }  
21         this.data = data;  
22     }  
23   
24     public boolean isSuccess() {  
25         return isSuccess;  
26     }  
27   
28     public void setSuccess(boolean isSuccess) {  
29         this.isSuccess = isSuccess;  
30     }  
31   
32     public String getErrorMsg() {  
33         return errorMsg;  
34     }  
35   
36     public void setErrorMsg(String errorMsg) {  
37         this.errorMsg = errorMsg;  
38     }  
39   
40     public String getSuccesMsg() {  
41         return succesMsg;  
42     }  
43   
44     public void setSuccesMsg(String succesMsg) {  
45         this.succesMsg = succesMsg;  
46     }  
47   
48     public Object getData() {  
49         return data;  
50     }  
51   
52     public void setData(Object data) {  
53         this.data = data;  
54     }  
55   
56 }  
   
 
重点,测试类
[java] view plain copy
  
 1 package net.test.testng.servicetest;  
 2   
 3 import java.sql.SQLException;  
 4   
 5 import net.test.testng.model.Result;  
 6 import net.test.testng.service.DataBaseDAO;  
 7 import net.test.testng.service.FunctionSwitch;  
 8 import net.test.testng.service.ToBeTestedService;  
 9   
10 import org.testng.Assert;  
11 import org.testng.annotations.AfterClass;  
12 import org.testng.annotations.AfterMethod;  
13 import org.testng.annotations.BeforeClass;  
14 import org.testng.annotations.BeforeMethod;  
15 import org.testng.annotations.Test;  
16   
17 public class ToBeTestedServiceTest {  
18   
19     protected FunctionSwitch functionSwitch;  
20   
21     protected DataBaseDAO dataBaseDAO;  
22   
23     protected boolean env;  
24   
25     protected ToBeTestedService toBeTestedService;  
26   
27     @BeforeClass  
28     public void initEnv() {  
29         env = functionSwitch.isAvaiable();  
30         if (functionSwitch.setAvaiable(true)) {  
31             Assert.fail("Prepare environment error!");  
32         }  
33     }  
34   
35     @BeforeMethod  
36     public void initData() {  
37         try {  
38             dataBaseDAO.insert("insert into db data...");  
39         } catch (SQLException e) {  
40             Assert.fail("Init database error!");  
41         }  
42     }  
43   
44     @Test  
45     public void testReturnString() {  
46   
47         String result = toBeTestedService.returnString();  
48   
49         Assert.assertNotNull(result);  
50   
51         Assert.assertEquals(result, "a string");  
52     }  
53   
54     @Test  
55     public void testReturnObject() {  
56           
57         Object result = toBeTestedService.returnObject();  
58   
59         Assert.assertNotNull(result);  
60   
61         if (!(result instanceof Result)) {  
62             Assert.fail("Error return type.");  
63         }  
64   
65         Assert.assertTrue(((Result) result).isSuccess());  
66   
67         Assert.assertNotNull(((Result) result).getSuccesMsg());  
68   
69         Object dbData = null;  
70         try {  
71             dbData = dataBaseDAO.readData("insert into db data...");  
72         } catch (SQLException e) {  
73             Assert.fail("read data from db error.");  
74         }  
75         Assert.assertEquals(((Result) result).getData(), dbData);  
76   
77     }  
78   
79     @AfterMethod  
80     public void cleanData() {  
81         try {  
82             dataBaseDAO.delete("insert into db data...");  
83         } catch (SQLException e) {  
84             Assert.fail("Delete database error!");  
85         }  
86     }  
87   
88     @AfterClass  
89     public void restoreEnv() {  
90         functionSwitch.setAvaiable(env);  
91     }  
92   
93 } 
 
 
说明:

1.其中beforeClass注解下,为整个test case运行所需要的基本环境,包括业务开关,上下游业务中所需要的其他服务的引入以及服务引入成功的判断,如果有一个服务都没有引入成功,其实该test case就没有必要执行,也就不需要浪费测试资源去执行了。

2.beforeMethod注解下,可以提供本次测试方法(服务中有两个方法,其中一个就依赖了数据库中的内容,所以要初始化数据库。)所依赖的环境信息。

3.两个after中,依次对数据和环境进行恢复,在CI情况下,本次执行的结果 有可能会影响到下次执行,所以,负责任的方法是,执行完本次test case后,就相应的进行环境和数据的清理,便于下次接口测试的顺利执行。

建议:

1.接口测试脚本的结构很重要,对于业务场景相似的情况,可以设置测试基类,将环境/数据的初始化放置在基类中;将测试执行和测试结果判断适当加以区分,这样逻辑会清晰,便于测试脚本维护。

2.提高脚本复用程度,如采取参数化驱动,使用csv/txt/excel构建测试数据驱动,编写自己的dataProvider,解析测试数据,提高脚本的利用率,如上述脚本中,针对returnObject方法,可以构建

a.数据初始化另一个返回结果

b.数据初始化为空

c.业务开关关闭

等情况,并且测试数据和测试结果一一对应,都进行参数化,加上正常场景,相当于进行了4个业务场景的测试,能够极大减少回归测试的人工。

3.为脚本执行后的副作用负责,主要是指,在脚本执行的过程中,难免会引入一些测试数据和对当前业务流的改动,在执行完成后,需要将这些执行痕迹清理和还原,一是便于手工测试的正常执行,而是为下次持续集成,减轻了错误概率。

原文地址:https://www.cnblogs.com/cheese320/p/8483437.html