使用iTest做Service Testing
创建测试工程
创建新工程
命令行输入以下命令,创建一个基于iTest的示例工程。
mvn archetype:generate -B -DarchetypeGroupId=com.taobao.itest.archetypes -DarchetypeArtifactId=itest-service-sample-archetype -DarchetypeVersion=1.3-SNAPSHOT -DarchetypeRepository=http://mvnrepo.taobao.ali.com/mvn/snapshots -DgroupId=com.taobao.qatest -DartifactId=mytestproject
该示例工程包含一些示例,略加修改就可以作为自己的测试工程。
已有工程引入iTest
如果已有的Maven工程需要引入iTest,在pom文件加入以下依赖。
<dependency> <groupId>com.taobao.test</groupId> <artifactId>itest</artifactId> <version>1.3-SNAPSHOT</version> <scope>test</scope> </dependency>
创建BaseTestCase
创建自己的BaseTestCase继承com.taobao.itest.ITestSpringContextBaseCase
public class BaseTestCase extends ITestSpringContextBaseCase{ }
加载Spring配置文件
用@ITestSpringContext注解标注类来声明Spring上下文,itest会在测试运行时据此位置完成Spring上下文加载和缓存。
@ITestSpringContext({"/applicationContext-test.xml"}) public class BaseTestCase extends ITestSpringContextBaseCase{ }
注意“/applicationContext-test.xml“以”/“打头表明从classpath根目录开始寻址,对于Maven标准目录结构而言applicationContext-test.xml应位于src/test/resources目录下。
可以加载多个配置文件
@ITestSpringContext({"/applicationContext.xml","/applicationContext-test.xml"}) public class BaseTestCase extends ITestSpringContextBaseCase{ }
子类默认继承父类声明的配置文件
@ITestSpringContext({"/base-context.xml“}) public class BaseTestCase extends ITestSpringContextBaseCase{ } @ITestSpringContext({"/extended-context.xml"}) public class ExtendedTest extends BaseTestCase { }
通过设置@ITestSpringContext的inheritLocations属性为false,会屏蔽掉标注于父类的配置文件。
Spring Bean实例化
测试时需要用到在Spring配置文件中定义的Bean,只需在测试类里定义并用@Resource注解标注即可完成其实例化。
public class UserManagerTest extends BaseTestCase { @Resource//用@Resource注解实例化bean(变量名跟配置文件中的bean id一致) protected UserManager userManager; }
数据加载管理
数据源配置
itest用Spring配置的数据源来加载数据文件,数据源类型无特殊要求,但建议用com.taobao.itest.jdbc.SchemaDataSource,itest会从效率等多方面考虑具体实现用哪个数据源。
<bean id="dataSourceTest" class="com.taobao.itest.jdbc.SchemaDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${dev-db1.jdbc.url}" /> <property name="username" value="${taobao.jdbc.username}" /> <property name="password" value="${taobao.jdbc.password}" /> </bean>
生成测试数据文件
你可以通过各种方式创建自己的测试数据,这里只介绍如何通过工具将其生成为符合特定格式的XLS文件或XML文件,供@ITestDataSet在测试用例运行时加载。
String destFilePath = "src/test/resources/UserManagerTest.xls";//目的文件,如果后缀为xml则生成xml文件 DataSource dataSource = DbEnum.DEV_ARK.getDataSource("username");//数据源 //ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-datasource.xml"); //DataSource dataSource = (DataSource)applicationContext.getBean("db1"); String querySqls = "SELECT * FROM bmw_userlinks WHERE id IN(1102710301,1102710302) ;" + //多个语句用分号分隔 "SELECT * FROM tbd_forbid_words WHERE id=11054101011"; //将符合条件的记录生成为符合DbUnit数据格式的xls文件或xml文件(根据destFilePath的后缀决定) DbUnitTools.generateDataSetFile(destFilePath, dataSource, querySqls);
测试数据加载与清理
默认加载
将上步生成的文件放到跟测试类同级classpath目录下,并用测试类来命名,对Maven标准目录结构,其位置关系如下:
src/test/java/ com/taobao/itest/sample/UserManagerTest.java src/test/resources com/taobao/itest/sample/UserManagerTest.xls
用@ITestDataSet注解标注测试类或方法,itest会在用例方法执行前加载数据到数据库,在用例方法执行完成后从数据库清理对应数据。
package com.taobao.test.sample; @ITestDataSet @ITestSpringContext({ "/datasource-test.xml" }) public class UserManagerTest extends BaseTestCase { @Test public void testGetGusets () { ... } @Test public void testGetUsersByNick() { ... } @Test public void testGetUsersByName() { ... } }
上例中itest从默认位置(相同classpath下跟类同名的xls文件)用默认数据源(在Spring配置文件中定义的唯一DataSource)用默认数据管理策略完成数据加载和清理。标注于类对该类所有的测试方法有效。
自定义数据文件位置
@ITestDataSet @ITestSpringContext({ "/datasource-test.xml" }) public class UserManagerTest extends BaseCase { @ITestDataSet("UserManagerTest_testGetUsers.xls") @Test public void testGetGusets () { ... } @Test public void testGetUsersByNick() { ... } @Test public void testGetUsersByName() { ... } }
上例中方法testGetGusets定义的@ITestDataSet覆盖了标注于类的@ITestDataSet,运行该方法时加载classpath:/com/taobao/itest/sample/UserManagerTest_testGetUsers.xls。 运行testGetUsersByNick和testGetGuestsByName这两个方法时将加载classpath:/com/taobao/itest/sample/UserManagerTest.xls。
自定义数据源名称
如果Spring上下文中有多个数据源,需指定DataSource名称。
package com.taobao.test.sample; @ITestDataSet(dsNames="aDataSource") @ITestSpringContext({ "/datasource-test.xml" }) public class UserManagerTest extends BaseCase { }
多数据集多数据源情况
@ITestSpringContext({ "/datasource-test.xml" }) public class UserManagerTest extends BaseCase { @ITestDataSet(locations = {"one.xls","another.xls"},dsNames={"aDataSource","bDataSource"}) @Test public void testGetUsersOrderBy () { }
上例中itest根据locations的dsNames定义的顺序,将用Spring Bean 名为”aDataSource“的数据源加载清理”one.xls“中的数据,用Spring Bean 名为”bDataSource“的数据源加载清理"another.xls"中的数据。
itest还提供用Excel的sheet名指定数据源,sheet名格式为dataSourceName.tableName。
自定义数据加载和清理策略
可用的策略及介绍如下
NONE:什么也不做 UPDATE :根据数据集内容更新表中数据 INSERT :将数据集内容插入表,可能会违反主键唯一约束 REFRESH :如果表中存在数据集中对应的数据则更新,不存在则插入 DELETE :从表中删除数据集中对应的内容 ---------下面三条在公用数据库中慎用---------------------- DELETE_ALL :删除表中所有数据 TRUNCATE_TABLE:执行truncate table指令 CLEAN_INSERT :先执行DELETE_ALL,再执行INSERT
@ITestDataSet默认的策略是加载用”REFRESH“,清理用”DELETE“,通过指定@ITestDataSet的setupOperation和teardownOperation属性可以自定义策略。
@ITestDataSet(setupOperation="INSERT",teardownOperation="NONE") public class UserManagerTest extends BaseCase { @Test public void testGetUsersByName() { ... } }
上面的例子中在执行前插入数据(若违反唯一索引抛异常),执行完成后选择不删除刚插入的数据。
支持无主键表
通常情况下,ITestDataSet根据数据库表主键完成插入和清理,有时候数据库表没有主键,在这种情况下使用ITestDataSet需要在excel里自定义主键。定义主键的方法很简单,在excel里将对应的字段名加下划线即可。
支持sysdate及sysdate加减天操作
有时我们希望插入的时间是动态的,当前时间或前后几天,这种情况在excel里把时间对应的字段值设置为sysdate表示动态替换为当前时间,设置为sysdate+n,或sysdate-n表示按当前时间加减n天(n为正整数,且1<=n<=31)
支持xml文件做为数据集
itest同样支持用xml做为数据文件,xml文件采用FlatXmlDataSet格式,可用前面介绍的DbUnitTools.generateDataSetFile工具生成xml文件,其格式示例如下
<?xml version='1.0' encoding='UTF-8'?> <dataset> <bmw_userlinks ID="1102710301" LINK_URL="http://1102730101" GMT_MODIFIED="1062478937000" TYPE="4" GMT_CREATE="1273556974000" USER_ID="1102710101" SHOP_ID="1102710301"/> <bmw_userlinks ID="1102710302" LINK_URL="http://1102730102" GMT_MODIFIED="1062478937000" TYPE="4" GMT_CREATE="1273556974000" USER_ID="1102710101" SHOP_ID="1102710302"/> <tbd_forbid_words ID="11054101011" FORBID_WORD="11054101011" MATCH_TYPE="2" WORD_TYPE="7" GMT_CREATE="1255431169000" GMT_MODIFIED="1255431169000" OPERATOR="wanglei01" DELETED="0"/> </dataset>
@ITestDataSet默认加载xls文件,如果要加载相同classpath目录下跟类同名的xml文件,需指定其fileType属性为xml。或者指定xml文件位置。
@ITestDataSet(fileType="xml") public class UserManagerTest extends BaseCase { @ITestDataSet("UserManagerTest_testGetUsers.xml") @Test public void testGetUsersByName() { ... } @Test public void testGetUsersByNick() { ... } }
断言验证
itest推荐用junit4新断言语法assertThat结合Hamcrest来实现风格统一,精确表达测试思想的断言,并通过扩展org.hamcrest.Matchers结合unitils实现反射相关的断言。
使用时需在测试类里导入包
import static org.junit.Assert.*; import static com.taobao.itest.matcher.Matchers.*;
下面是一些常用的示例
字符相关匹配符
/**equalTo匹配符断言被测的testedValue等于expectedValue,equalTo可以断言数值之间,字符串之间和对象之间是否相等,相当于Object的equals方法*/ assertThat(testedValue, equalTo(expectedValue)); /**equalToIgnoringCase匹配符断言被测的字符串testedString在忽略大小写的情况下等于expectedString*/ assertThat(testedString, equalToIgnoringCase(expectedString)); /**equalToIgnoringWhiteSpace匹配符断言被测的字符串testedString在忽略头尾的任意个空格的情况下等于expectedString,注意:字符串中的空格不能被忽 略*/ assertThat(testedString, equalToIgnoringWhiteSpace(expectedString); /**containsString匹配符断言被测的字符串testedString包含子字符串subString**/ assertThat(testedString, containsString(subString) ); /**endsWith匹配符断言被测的字符串testedString以子字符串suffix结尾*/ assertThat(testedString, endsWith(suffix)); /**startsWith匹配符断言被测的字符串testedString以子字符串prefix开始*/ assertThat(testedString, startsWith(prefix));
一般匹配符
/**nullValue()匹配符断言被测object的值为null*/ assertThat(object,nullValue()); /**notNullValue()匹配符断言被测object的值不为null*/ assertThat(object,notNullValue()); /**is匹配符断言被测的object等于后面给出匹配表达式*/ assertThat(testedString, is(equalTo(expectedValue))); /**is匹配符简写应用之一,is(equalTo(x))的简写,断言testedValue等于expectedValue*/ assertThat(testedValue, is(expectedValue)); /**is匹配符简写应用之二,is(instanceOf(SomeClass.class))的简写,*断言testedObject为Cheddar的实例 */ assertThat(testedObject, is(Cheddar.class)); /**not匹配符和is匹配符正好相反,断言被测的object不等于后面给出的object*/ assertThat(testedString, not(expectedString)); /**allOf匹配符断言符合所有条件,相当于“与”(&&)*/ assertThat(testedNumber, allOf( greaterThan(8), lessThan(16) ) ); /**anyOf匹配符断言符合条件之一,相当于“或”(||)*/ assertThat(testedNumber, anyOf( greaterThan(16), lessThan(8) ) );
数值相关匹配符
/**closeTo匹配符断言被测的浮点型数testedDouble在20.0??0.5范围之内*/ assertThat(testedDouble, closeTo( 20.0, 0.5 )); /**greaterThan匹配符断言被测的数值testedNumber大于16.0*/ assertThat(testedNumber, greaterThan(16.0)); /** lessThan匹配符断言被测的数值testedNumber小于16.0*/ assertThat(testedNumber, lessThan (16.0)); /** greaterThanOrEqualTo匹配符断言被测的数值testedNumber大于等于16.0*/ assertThat(testedNumber, greaterThanOrEqualTo (16.0)); /** lessThanOrEqualTo匹配符断言被测的testedNumber小于等于16.0*/ assertThat(testedNumber, lessThanOrEqualTo (16.0));
集合相关匹配符
/**hasEntry匹配符断言被测的Map对象mapObject含有一个键值为"key"对应元素值为"value"的Entry项*/ assertThat(mapObject, hasEntry("key", "value" ) ); /**hasItem匹配符表明被测的迭代对象iterableObject含有元素element项则测试通过*/ assertThat(iterableObject, hasItem (element)); /** hasKey匹配符断言被测的Map对象mapObject含有键值“key”*/ assertThat(mapObject, hasKey ("key")); /** hasValue匹配符断言被测的Map对象mapObject含有元素值value*/ assertThat(mapObject, hasValue(value));
反射相关匹配符
/**断言两个对象所有属性值相等*/ assertThat(JavaBeanObjectTested,propertiesEquals(JavaBeanObjectExpected)); /**断言两个对象指定属性值相等*/ assertThat(JavaBeanObjectTested,propertiesEquals(JavaBeanObjectExpected,property1,propertity2)); /**断言两个对象 除指定属性外其他属性值相等*/ assertThat(JavaBeanObjectTested,excludedPropertiesEquals(JavaBeanObjectExpected,property1,propertity2));
自动打印调用入参和结果
由于“Service Testing”的接口一般是JavaBean对象,通常包含N多的字段,测试时需要对相关字段赋值。有时(尤其是用例运行第一次失败时)需要知道调用的确切入参是什么,以检查构造测试数据是否正确,需要知道调用返回的确切结果是什么,以检查断言语句是否正确。
itest提供的LogInterceptor可以通过配置自动打印出调用入参和结果。LogInterceptor采用Spring Aop的思路实现,其配置示例如下
<bean id="logInterceptor" class="com.taobao.testsupport.spring.aop.LogInterceptor"> <property name="logInvokeParams" value="true" /> <property name="logInvokeResult" value="true" /> </bean> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <value>guestManager</value> </property> <property name="interceptorNames"> <list> <value>logInterceptor</value> </list> </property> </bean>
通过上面的配置为guestManager这个Bean注入了自动打印调用入参和结果功能。
package com.taobao.test.sample; public class GuestManagerTest extends BaseCase { @Resource protected GuestManager guestManager; @Test public void testGetGusetsByName () { Guest guest = populate (Guest.class); List <Guest> guests = guestManager.getGuests(guest); } }
执行上面的测试将会打印出类似下面的日志
GuestManagerTest.testGetGusets(33) |GuestManagerImpl.getGuests invoked with params: param 1: com.taobao.testsupport.sample.model.Guest@1d47b2b[ id=<null> trackid=0a63263401ac269422217a09cc3 lastNick=James Gosling ] GuestManagerTest.testGetGusets(33) |GuestManagerImpl.getGuests invoked result is: [com.taobao.testsupport.sample.model.Guest@1700391[ id=88001 trackid=0a63263401ac269422217a09cc3 lastNick=James Gosling ]]
注意LogInterceptor的功能开启需要在log4j里设置com.taobao.itest日志级别为debug
<logger name="com.taobao.itest"> <level value="DEBUG" /> </logger>
Webx Testing
概述
“Webx”是阿里巴巴的web框架(wiki:http://code.taobao.org/trac/webx/wiki/ZhWikiStart ), “Webx Testing”的思路是通过Servlet为测试介入点,模拟Web容器,通过封装参数(url,request param,session,cookie等)完成对Web Module(Action/Screen)的调用,调用完毕可对Servlet中的对象(Rundata、Context)进行校验。下图展示了大致原理。
同样要说明的是,这里的“Webx Testing”跟传统的单元测试是不同的,“Webx Testing”不仅仅是测试Web层的Module(Action/Screen)逻辑代码,而是通过透传的方式测试到后面各个层,确保Web Module对外提供的功能正确性。相较于“Service Testing”,“Webx Testing”是更大集成情况下的测试,因此环境配置要比“Service Testing”复杂。
单元测试、“Service Testing”和“Webx Testing”到底搞哪个?答案是具体问题具体分析。一般来讲单元测试是开发人员必做的,有效的单元测试可以尽早的发现代码逻辑bug,减小集成测试失败的概率,对于bug的快速定位也非常有好处,但这个前提是单元测试的编写和执行要快,要成本低。如果时间紧又想收益高,建议开发人员做“Service Testing”,与单元测试要测每层每个细小的功能相比,“Service Testing”保证了整合起来的功能是能对外提供正确服务的,不仅仅覆盖了代码逻辑,还覆盖了各种用户使用场景(接口为谁服务,客户会怎么用)。如果有大量的业务/代码逻辑在Web层,那么“Webx Testing”是不错的选择,跟“Service Testing”相比,“Webx Testing”具有更大的覆盖率、更贴近上层业务需求、用例编写更容易等优势。
使用iTest-webx
创建测试工程
创建新工程
命令行输入以下命令,创建一个示例工程(如果是webx2修改下面命令中的itest-webx3-sample-archetype为itest-webx-sample-archetype))。
mvn archetype:generate -B -DarchetypeGroupId=com.taobao.itest.archetypes -DarchetypeArtifactId=itest-webx3-sample-archetype -DarchetypeVersion=1.3-SNAPSHOT -DarchetypeRepository=http://mvnrepo.taobao.ali.com/mvn/snapshots -DgroupId=com.taobao.qatest -DartifactId=mytestproject
该示例工程包含一些示例,根据创建工程后的readme.txt说明略加修改就可以作为自己的测试工程了,但建议你了解细节。
已有工程引入itest-webx
如果已有的Maven工程需要引入itest-webx3,在pom文件加入以下依赖(如果是webx2修改下面的itest-webx3为itest-webx)。
<dependency> <groupId>com.taobao.test</groupId> <artifactId>itest-webx3</artifactId> <version>1.3-SNAPSHOT</version> <scope>test</scope> </dependency>
itest-webx框架会自行依赖itest的匹配版本,因此不需要再引入itest。
创建BaseTestCase
创建自己的BaseTestCase继承com.taobao.itest.web.webx.ITestWebxBaseCase.
public class BaseTestCase extends ITestWebxBaseCase{ }
声明Web上下文
用@ITestWebContext注解标注于测试类声明web.xml文件的位置。
@ITestWebContext(webXml="target/petstore/WEB-INF/web.xml")//被测war包web.xml文件 public class BaseTestCase extends ITestWebxBaseCase{ }
模拟Web容器的类加载
用@ITestClassLoader注解标注与测试类,itest框架在运行时会根据该注解加载被测war包/WEB-INF/lib下的jar文件及classes目录下的文件。
@ITestClassLoader @ITestWebContext(webXml="target/petstore/WEB-INF/web.xml")//被测war包web.xml文件 public class BaseTestCase extends ITestWebxBaseCase{ }
准备入参
iTest框架提供两种方式组织web请求入参,可结合使用。
编码方式
在准备入参前先想下完成某个web请求需要哪些类型的参数?最基本的我们需要url,需要参数,或许还需要Session和Cookie。这些都可以调用基类的方法实现。
setUrl(url) //设置要调用的url addRequestParam(parameterName,parameterValue) //设置请求参数 addSessionParam(parameterName,parameterValue) //设置Session addCookieParam(String parameterName,parameterValue)//设置Cookie addFileParam(String parameterName,String filepath)//设置上传文件 addHeaderParam(String parameterName,String parameterValue)//设置Header
Webx框架对于表单参数会做特殊处理,比如业务上我们需要某个表单有phoneCode字段,开发会在form.xml里做类似配置
<form> <group name="register"> <field name="phoneCode" displayName="电话号码"> ... </field> </group> </form>
经Webx渲染到页面后phoneCode被转为_fma.b._0.pho,这样提交请求后传给服务端的实际参数名是_fma.b._0.pho,而不是phoneCode。
但我们测试时需要维护phoneCode这个可读性好的明文,对于这类表单参数的设置需调用基类的addGroupParam方法,iTest框架会在实际调用时做自动转换。
addGroupParam(groupName,parameterName,parameterValue)//设置表单参数 addGroupFileParam(String groupName,String parameterName,String filepath)//设置表单上传文件
配置方式
还可以把参数放在一个xml文件里
创建xml文件,以“测试类名+Param.xml”命名,放在跟测试类同名的classpath目录下。
src/test/java/ com/alibaba/sample/petstore/web/user/RegisterActionTest.java src/test/resources com/alibaba/sample/petstore/web/user/RegisterActionTestParam.xml
用@ITestWebParam标注于类自动装置输入参数
@ITestWebParam public class RegisterActionTest extends BaseTestCase{ }
关于XML格式的详细信息可参考Web层测试入参XML详解,
下面是一个参考示例。
<?xml version="1.0" encoding="GBK" ?> <tests url="user/register.htm"> <general id="global"> <param name="action" value="RegisterAction"/> <param name="event_submit_do_register" value="立即注册"/> <session name="_csrf_token" value="abc" /> <param name="_csrf_token" value="abc" /> <header name="user-agent" value="test"/> <group name="register"> <param name="userId" displayName="登录名" value="test11" /> <param name="password" displayName="密码" value="test12" /> </group> </general> <test name="testRegisterUserWithRightParam"> <include id="global" /> <include file="classpath:com/taobao/qatest/publicParam.xml" id="global"/> <group name="register"> <param name="passwordConfirm" displayName="密码验证" value="test12" /> <file name="pic" displayName="图片" value="classpath:uploadfile/xx.jpg" /> </group> </test> </tests>
有些参数是多个测试类之间共享的,这类参数可以放到一个单独的xml文件里,以includes为根节点,下面可包含多个general节点。
<includes> <general id="global"> <session name="_tb_token_" value="abc" /> <param name="_tb_token_" value="abc" /> </general> </includes>
引用公共文件参数的方式如下:
<include file="classpath:com/taobao/qatest/publicParam.xml" id="global"/>
使用参数生成工具
“参数太多太杂,尤其是第一个用例,根本不知道该传哪些参数”,如果你也有这样的困惑,请使用itest-webx测试参数生成工具。
适用范围:对已开发完成的功能补webx测试
使用前置条件:会部署自己的应用在本地跑起来,知道对应的ear/war或部署目录的位置。
快速使用三部曲:
1. 下载工具包:访问http://itest.taobao.net:8088/fileadmin/?sort=1&dir=%2Fhome%2Fitest%2Ffiles%2Fitest-files 进入“itest-webx测试参数文件生成工具”, 下载itest-webx-tools.jar最新版本至本地目录,如d:盘 2. 处理部署包:打开cmd输入java -jar D:/itest-webx-tools.jar,根据提示输入应用的ear/war或部署目录位置。 3. 重启jboss,页面上走下对应的功能,在d:/itestXML生成itest-webx测试参数文件。
执行Web Module
执行Web Module非常简单,在测试方法(方法名在入参XML里定义)里调用基类的performWebModule()方法即可。
public class RegisterActionTest extends BaseTestCase{ @Test public void testRegisterUserWithRightParam() throws MalformedURLException, IOException, Exception{ //执行被测Web Module(Action/Screen) super.performWebModule(); } }
验证
对数据库的验证跟其他层测试验证一样,对Action/Screen返回值的验证,基类对常用的验证点提供了方法供子类调用,这类方法以verify打头。
public class RegisterActionTest extends BaseTestCase{ @Test public void testRegisterUserWithRightParam() throws MalformedURLException, IOException, Exception{ super.performWebModule(); //验证重定向 super.verifyRedirectLocation("http://localhost/user/register_account.htm"); //验证session内容 super.verifySessionHasKey("petstoreUser"); //验证DB内容 ... } }
Web层测试入参XML详解
入参XML文件以tests为根节点,属性url为Action/Screen所对应的url。
以cookie、session和param节点定义不同类型的入参,这些节点可以被general节点和test节点包含。
general节点用于定义公用的参数被test节点引用。
test节点代表一个测试方法,其属性name的值跟测试方法名一致,可用include节点引用general节点定义的公共参数。
单个测试参数(cookie,session,param)
Web层的参数可大致分为cookie,session和request域的参数,分别用以下三类节点定义Action/Screen参数。每个节点有name和value两个必选属性,形成key-value对。desc节点是可选的,用于增强阅读性,程序不会引用到。 ?
cookie定义存放在cookie里的参数
<cookie name="x" value="175754637"/>
session定义存放在session里的参数
<session name="userID" value="42596d9570f"/>
param定义存放在request里的参数
<param name="phoneCode" value= "12314355" displayName"电话号码"/>
上传文件(file)
<file name="pic" value="src/test/resources/upload/xx.jpg"/>
表单参数
webx对表单参数会做特殊处理,这类参数需用group节点包含。
<group name="register"> <param name="userId" displayName="登录名" value="test11" /> <param name="password" displayName="密码" value="test12" /> <file name="pic" value="src/test/resources/upload/xx.jpg"/> </group>
公用测试参数(general)
有些参数会被多个用例用到,为了减少重复,可以把这些参数抽取出来,供多个用例引用。我们用general节点将公用的参数包装起来,general节点有一个必选属性id,用于被测试用例test节点引用。
<general id="global"> <param name="action" value="RegisterAction"/> <param name="event_submit_do_register" value="立即注册"/> <session name="_csrf_token" value="abc" /> <param name="_csrf_token" value="abc" /> <group name="register"> <param name="userId" displayName="登录名" value="test11" /> <param name="password" displayName="密码" value="test12" /> </group> </general>
引用公用数据的标签为include,如include id=”login”/
测试用例/方法(test)
用test定义一个测试用例(方法)。test节点只有一个属性name,其值跟测试方法名相同。test节点可包含多个cookie、session、param节点。test节点还可包含多个include节点,引入general节点定义的参数。
<test name="testRegisterUserWithRightParam"> <include id="global" /> <group name="register"> <param name="passwordConfirm" displayName="密码验证" value="test12" /> </group> </test>
测试类(tests)
每个测试类对应一个xml文件,tests为根节点,属性url为Action/Screen所对应的url。
tests节点可包含多个general节点和test节点
测试环境特定配置
执行“Service Testing”或“Webx Testing”时,大多数的配置文件不需要修改,部分配置需要修改或专门处理,如测试数据源和HSF服务。
测试环境数据源
如果数据源用到了Jndi,由于测试环境不支持Jndi,所以需要修改为测试用数据源,在Spring配置文件中按以下方式配置数据源(注意需将变量替代为实际值)
<bean id="dataSource" class="com.taobao.itest.jdbc.SchemaDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${dev-db1.jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean>
覆盖生产配置
“Service Testing”可以通过在单独的Spring配置文件里配置跟生产环境同名的Bean,用@ITestSpringContext将测试用配置文件后加载来达到覆盖生产环境Bean的目的。
@ITestSpringContext({"/applicationContext.xml","/applicationContext-test.xml"}) public class BaseTestCase extends ITestSpringContextBaseCase {
在上面的例子中,applicationContext-test.xml配置的Spring Bean会覆盖applicationContext.xml中同名的Spring Bean.
“Webx Testing”可以通过在src/test/config/WEB-INF目录下放置跟被测war包对应目录同名文件来达到覆盖生产环境配置的目的。
测试环境Hsf配置
如果用到了Hsf服务,按以下方式配置。 在pom文件中引入
<dependency> <groupId>com.taobao.hsf</groupId> <artifactId>hsfstarter</artifactId> <version>1.0.1-SNAPSHOT</version> <scope>test</scope> </dependency> <dependency> <groupId>com.taobao.hsf</groupId> <artifactId>hsfunit</artifactId> <version>1.0.1-SNAPSHOT</version> <scope>test</scope> </dependency>
在src/test/resources目录下新建文件hsfconfig.properties,内容如下
hsf.server.port=12200 hsf.server.min.poolsize=10 hsf.server.max.poolsize=600 hsf.run.mode=1 hsf.client.localcall=true
在测试基类BaseTestCase里加上@ITestHsfStarter注解
@ITestHsfStarter(path="/home/admin/hsf",version="1.4.8.3")//启动hsf单测环境服务,请删除原来的static硬编码 public class BaseTestCase extends ITestWebxBaseCase {
运行时会检查指定目录是否存在hsf对应的版本,如果不存在,会自动下载,然后启动HSF服务。