TestNG中单元测试和集成测试(十二)
TestNg作为单元测试框架,不仅仅可以适用于单元测试,其实在自动化测试的技术栈知识体系中,单元测试框
架是必须需要掌握的知识体系之一,因为不管我们是做API的自动化测试还是基于UI的自动化测试,都需要对测试用
例进行管理和执行,那么也就涉及到单元测试框架里面的知识体系,如测试用例,测试套件,测试执行以及测试报
告的这些信息。在集成测试中更多需要考虑的是各个服务之间的集成测试,淘宝是在微服务的架构体系下,测试一
个完整的链路场景可能涉及多个服务,但是如果服务并不能够正常的执行,那么就需要mock的思想来解决这些事
情,这些也是TestNG测试框架体系里面需要来解决的问题。在UI的自动化测试中,相对而言是比较简单的,TestNG
测试框架可以很轻松的和WebDriver测试框架来整合起来,从而形成基于UI自动化测试的体系。
我们先来看单元测试,单元测试顾名思义就是对测试对象最小粒度的测试,主要测试的是一个类里面的具体方法的逻辑,异常处理
以及超时机制,针对不同的类以及不同的业务形态,考虑的单元测试场景是维度也是有差异的,但是我们主要案例是基于测试它的功能
性的维度,并不考虑其他的维度体系。具体测试案例代码如下所示:
package test.unit.mock; import java.util.ArrayList; import org.testng.Assert; import org.testng.annotations.*; public class UnitTest { ArrayList<String> listObj=new ArrayList<>(); @BeforeClass public void beforeClass() { listObj.add("Python"); listObj.add("Java"); listObj.add("C"); } @Test(description = "验证第一个值的准确性") public void test_unit_one() { String data=listObj.get(0); Assert.assertEquals(data,"Python","测试验证通过"); } @Test( expectedExceptions = IndexOutOfBoundsException.class, description = "验证异常信息的判断") public void test_unit_two() { listObj.get(4); } @Test(description = "验证List的长度") public void test_unit_three() { Assert.assertTrue(listObj.size()==3); } }
在如上的案例中,我们主要编写了验证一个List集合里面对象值的准确性,以及长度和异常信息的处理,执行如上的代码后,后会输出如下
的信息:
===============================================
Simple Logger Suite
Total tests run: 3, Failures: 0, Skips: 0
===============================================
下来我们来看mock的对象这部分,我们首先来思考为什么需要这样的一个场景来进行测试,举一个很常见的案例,在物联网的
测试场景中,要测试一个车辆进行后它的支付金额的信息,那么这地方就涉及到车辆进入涉及到的车辆信息,以及支付这个环节中
我们需要通过mock的方式来验证这样的场景。模拟对象,更加精确的可以描述为模拟主要用于执行单元测试。在编写单元测试时,
所测试的代码可能依赖于代码中的另一个类对象或类方法。此从属代码可能可用于测试,也可能不能用于测试。为了将受测试代码
的行为与从属代码的行为隔离,我们使用模拟技术。模拟允许用户创建受测试代码所依赖的模拟对象和行为。模拟对象基本上模拟
从属代码的行为,以便可以完成对受测试代码的单元测试。简单的模拟框架如moco,下载它之后直接执行就可以运行了,使用的主
要是JSON 文件来进行模拟,这地方主要讲的是mockit的程序,我们首先需要在pom.xml文件中引入它,具体pom.xml文件的内容
为:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>ngApp</artifactId> <version>1.0-SNAPSHOT</version> <properties> <!--编译编码--> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <aspectj.version>1.8.10</aspectj.version> </properties> <dependencies> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.10</version> <scope>compile</scope> </dependency> <!--WebDriver的测试框架--> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>3.141.59</version> </dependency> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-server</artifactId> <version>3.141.59</version> </dependency> <!--引入Allure的框架--> <dependency> <groupId>io.qameta.allure</groupId> <artifactId>allure-testng</artifactId> <version>2.0-BETA14</version> <scope>test</scope> </dependency> <!--log4的模块--> <!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!--fastjson库--> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency> <!--单元测试覆盖率信息--> <!-- https://mvnrepository.com/artifact/org.jacoco/jacoco-maven-plugin --> <dependency> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.6</version> <scope>test</scope> </dependency> <!--mockito框架--> <!-- https://mvnrepository.com/artifact/org.mockito/mockito-all --> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.10.19</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <!--Alure测试报告插件--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.20</version> <configuration> <argLine> -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar" </argLine> <!--生成allure-result的目录--> <systemProperties> <property> <name>allure.results.directory</name> <value>./target/allure-results</value> </property> </systemProperties> </configuration> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectj.version}</version> </dependency> </dependencies> </plugin> <!--检查代码覆盖率的插件配置--> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.6</version> <executions> <execution> <id>prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> <configuration> <!--指定jacoco.exec的目录--> <destFile>target/jacoco.exec</destFile> <propertyName>jacocoArgLine</propertyName> </configuration> </execution> <execution> <id>check</id> <goals> <goal>check</goal> </goals> </execution> <execution> <id>report</id> <phase>prepare-package</phase> <goals> <goal>report</goal> </goals> </execution> </executions> <!-- Configuration 里面写配置信息 --> <configuration> <!-- rules里面指定覆盖规则 --> <rules> <rule implementation="org.jacoco.maven.RuleConfiguration"> <element>BUNDLE</element> <limits> <!-- 指定方法覆盖到80% --> <limit implementation="org.jacoco.report.check.Limit"> <counter>METHOD</counter> <value>COVEREDRATIO</value> <minimum>0.80</minimum> </limit> <!-- 指定指令覆盖到80% --> <limit implementation="org.jacoco.report.check.Limit"> <counter>INSTRUCTION</counter> <value>COVEREDRATIO</value> <minimum>0.80</minimum> </limit> <!-- 指定行覆盖到80% --> <limit implementation="org.jacoco.report.check.Limit"> <counter>LINE</counter> <value>COVEREDRATIO</value> <minimum>0.80</minimum> </limit> <!-- 指定类覆盖到100%,不能遗失任何类 --> <limit implementation="org.jacoco.report.check.Limit"> <counter>CLASS</counter> <value>MISSEDCOUNT</value> <maximum>0</maximum> </limit> </limits> </rule> </rules> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.14.1</version> <configuration> <!--testng配置文件名称--> <suiteXmlFiles> <suiteXmlFile>testng.xml</suiteXmlFile> </suiteXmlFiles> <threadCount>1</threadCount> <parallel>tests</parallel> <!--测试失败后忽略继续执行--> <testFailureIgnore>true</testFailureIgnore> <skipTests>false</skipTests> <argLine>-Xmx256M ${jacocoArgLine}</argLine> </configuration> </plugin> </plugins> </build> </project>
引入后,下面我们使用具体的案例来演示这部分的应用,我们使用mockito来模拟一个简单的案例测试,
具体测试案例代码如下:
package test.unit.mock; import org.mockito.Mock; import org.omg.CORBA.INTERNAL; import org.testng.Assert; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import static org.mockito.Mockito.*; public class MockitoTest { //创建mock的对象 @Test public void test_mock_one() { //使用mock静态方法创建Mock对象 List objMock=mock(List.class); Assert.assertTrue(objMock instanceof List); ArrayList mock=mock(ArrayList.class); Assert.assertTrue(mock instanceof ArrayList); } @Test(description = "配置mock的对象") public void test_mock_two() { List mock=mock(List.class); when(mock.add("Python")).thenReturn(true); when(mock.size()).thenReturn(1); Assert.assertTrue(mock.add("Python")); Assert.assertEquals(mock.size(),1); } @Test(description = "模拟一个Iterator对象") public void test_mock_iterator() { Iterator t=mock(Iterator.class); when(t.next()).thenReturn("Hi,").thenReturn("无涯"); String results=t.next()+""+t.next(); Assert.assertEquals("Hi,无涯",results); } @Test(description = "mock一个方法的调用") public void test_mock_method() { List<String> mock=mock(List.class); mock.add("Python"); mock.add("Java"); mock.add("Go"); when(mock.size()).thenReturn(3); Assert.assertEquals(mock.size(),3); verify(mock,never()).isEmpty(); verify(mock,times(1)).add("Python"); } }
从上信息我们可以得到,我们首先需要创建一个模拟对象,然后通过静态方法把这个模拟对象进行处理后,
然后来验证模拟对象它的结果的准确性。我们可以再看一个案例,编写Person的接口,源码为:
package test.unit.mock; public interface Person { public String show(); }
编写继承接口的类,它的源码信息为:
package test.unit.mock; public class PersonInterface implements Person { @Override public String show() { return "Hello Mockito"; } public String getName() { return ""; } }
我们编写测试类,来模拟PersonInterface类的实例化后的对象,模拟调用show()的方法,改变它的输出信
息,再来验证它的结果的准确性,测试案例的源码如下:
package test.unit.mock; import org.testng.Assert; import org.testng.annotations.Test; import static org.mockito.Mockito.*; public class PersonMock { @Test(description = "测试接口类") public void test_mock_one() { PersonInterface mock=mock(PersonInterface.class); when(mock.show()).thenReturn("Mockitio"); Assert.assertEquals(mock.show(),"Mockitio"); } @Test public void test_mock_two() { PersonInterface mock=mock(PersonInterface.class); String str1="无涯课堂为您服务!"; when(mock.getName()).thenReturn(str1); Assert.assertEquals(mock.getName(),str1); } }
然后执行来验证它的结果信息的输出。所有的验证结果信息都是符合我们的期望结果的,它的执行结果信息是pass。
感谢您的阅读,后续会持续更新!

浙公网安备 33010602011771号