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。

      感谢您的阅读,后续会持续更新! 

posted @ 2021-01-24 23:29  无涯(WuYa)  阅读(552)  评论(0)    收藏  举报