• pytest与testNg自动化框架


    一.pytest

    1.安装pytest: pip install pytest
    2.编写用例 - 收集用例 - 执行用例 - 生成报告
    3.pytest如何自动识别用例

     识别规则如下:
    1、搜索根目录:默认从当前目录中搜集测试用例,即在哪个目录下运行pytest命令,则从哪个目录当中搜索;
    2、搜索规则:
    1)搜索文件:符合命名规则 test_*.py 或者 *_test.py 的文件
    2)在满足1)的文件中识别用例的规则:
    2.1)以test_开头的函数名;
    2.2)以Test开头的测试类(没有__init__函数)当中,以test_开头的函数
    4.根据标记名运行测试用例
    在pytest当中,先给用例打标记,在运行时,通过标记名来过滤测试用例。
    1)注册标签名
    通过pytest.ini配置文件注册。在pytest.ini文件当中:
    [pytest] # 固定的section名
    markers= # 固定的option名称
      标签名1: 标签名的说明内容。
      标签名2
      标签名N
    2)在测试用例/测试类中给用例打标记(只能使用已注册的标记名)
    在 测试用例的前面加上:@pytest.mark.已注册标签名
    3)调用pytest.main()函数,将运行时的参数以列表传进去
    根据标签名过滤用例的参数为:-m 标签名
    5.fixture用法
    我们在编写测试用例,都会涉及到用例执行之前的环境准备工作,和用例执行之后的环境清理工作。
    用例执行之前的环境准备工作代码(前置工作代码)
    用例执行之后的环境清理工作(后置工作代码)
    通常,在自动化测试框架当中,都叫做fixture。
    通过@pytest.fixture装饰器来定义fixture。一个函数被@pytest.fixture装饰,那么这个函数就是fixture。
    使用fixture时,分为二个部分:fixture定义、fixture调用。
    除此之外,还有fixture的共享机制,嵌套调用机制。
    1)定义fixture
    前置准备工作代码和后置清理工作代码,都写在一个函数里面。通过yeild关键字,区分前置代码和后置代码 。yeild之前的代码为前置代码,yeild之后的代码为后置代码,在实际应用场景当中,可以只有前置准备工作代码,也可以只有后置清理工作代码。
    fixture有4个作用域:测试会话(session)、测试模块(module)、测试类(class)、测试用例(function)
    通过@pytest.fixture(scope=作用域)来设置。默认情况下,scope=function
    session:pytest执行测试用例的整个过程,称为会话
    设置scope为session。autouse表示自动使用,一般 function、class、module 级别的 fixture,都不会去开启 autouse=True
    @pytest.fixture(scope=“session”,autouse=True)
    def init3():
    yield
    print(“用例执行之后,执行的代码”) # 只有用例执行之后的后置清理代
    2)fixture的返回值设置:yeild 返回值(前置代码里的变量,要传递给测试用例去使用。那么首先,就得fixture函数返回变量才行。)
    3)调用fixture
    调用方法有2种:

    • 在测试用例/测试类上面加上:@pytest.mark.usefixture(“fixture的函数名字”)
    • 将fixture函数名,作为测试用例函数的参数(当用这一种时,第一种可不用)
      6.conftest.py共享机制
      在某些大的业务场景下,很多用例当中,会使用相同的前置准备工作,和后置清理工作。
      pytest框架提供了一个fixture共享的机制 ,可以让不同的用例模块,使用同一个fixture。这就是conftest.py文件。在测试用例文件当中,不需要引入conftest.py文件。直接调用fixture的函数名,会自动去conftest.py当中查找的。
      1)conftest.py层级作用域
      conftest.py 在哪个目录下,此目录下(包含子目录)的所有用例可使用其中的fixture
      根目录下的conftest.py,作用域是整个项目。
      某个python包内,作用域就是该包内
      那么有个问题,如果出现了同名fixture怎么办呢?
      这里涉及到了,测试用例在执行时,调用fixture的顺序。一般来讲,按 就近原则 调用。
      测试用例文件中的fixture > 当前目录中的fixture > 上级目录中的fixture > 根目录中的fixture
      7.fixture嵌套
      嵌套使用即:一个fixture,可以做另外一个fixture的参数,即 init()可作为ini_req_assert函数的入参
      如果用例当中,调用了func_fix3,那么执行顺序为:
      【低级别可调用高级别或同级别 ,反之则不行】
      func_fix的前置
      func_fix3的前置
      ----测试用例----
      func_fix3的后置
      func_fix的后置
    @pytest.fixture(scope="class")
    def func_fix():
        print("---- 注册帐号 开始1 -----")
        yield True
        print("---- 注册帐号 结束4 -----")
    
    @pytest.fixture
    def func_fix3(func_fix):
        print("****  登陆账号2 ****")
        print(func_fix)
        yield func_fix
        print("****  登陆完成3 ****")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    8.数据驱动
    在测试用例方法上打标签@pytest.mark.parametrize(“case”, cases)
    9.并发测试
    一般是利用第三方插件pytest-xdist,前提是用例之间没有依赖关系且执行是没有顺序的,所以不适合接口自动化
    10.失败重试
    有利于提高自动化用例的稳定性,可以通过pytest的pytest-rerunfailures插件来实现用例重跑,具体有两种形式,一种是全局通过命令行: Pytest --reruns 2 --reruns-delay 5,一种是局部在案例方法上打标记@pytest.mark.flaky(reruns=2, reruns_delay=1)

    11.pytest跳过测试用例

    1.无条件跳过------@pytest.mark.skip()
    在测试方法或类前面加上装饰器@pytest.mark.skip(reason=None),表示该条测试用例不执行,参数reason代表跳过的原因,reason可省略
    2.有条件跳过------@pytest.mark.skipif()
    @pytest.mark.skipif(condition, reason=“xxx”)
    说明:condition—跳过的条件,如果为True则跳过该函数,如果为False则不跳过
    12.pytest执行顺序
    利用pytest-ordering插件,通过装饰器@pytest.mark.run(order=1)来进行控制,数字越小,越前执行

    13.pytest参数化作用域
    @pytest.mark.parametrize()装饰器方式进行参数化
    pytest.fixture()方式进行参数化,fixture装饰的函数可以作为参数传入其他函数
    conftest.py文件中存放参数化函数,可作用于模块内的所有测试用例
    14.为测试用例设置超时时间
    可以使用pytest-timeout插件来为测试用例设置超时时间
    15.pytest优势
    直接使用assert进行断言
    失败用例提供非常详细的错误信息
    自动发现和收集测试模块和用例
    灵活的fixture管理
    mark用例标记
    丰富的插件系统
    支持失败重试
    兼容了unittest
    16.unittest和pytest的区别
    1.用例设计规则
    unittest:
    (1)试类必须继承unittest.TestCase
    (2)测试函数必须以”test_”开头
    pytest:
    (1)测试文件的文件名必须以”test_”开头,或者以”_test”结尾
    (2)测试类命名必须以”Test”开头
    (3)测试函数名必须以”test”开头
    2.断言
    unittest:
    assertXXX
    pytest:
    直接使用assert进行断言
    3.用例前置和后置
    unittest:
    (1)通过setup每个用例执行前执行,teardown每个用例执行后执行
    (2)通过setupclass类里面所有用例执行前执行,teardownclass类里面所有用例执行后执行
    每个测试文件必须单独设置前后置
    pytest:
    通过fixture夹具可以自定义pytest的前置和后置,yield之前是为前置,yield之后为后置,格式@pytest.fixture(scope=“XXX”),scope:有四个级别,function(默认),class,module,session
    创建conftest.py文件,当前目录下所有的测试文件都能自动调用该夹具
    4.参数化
    unittest:参数化需要依赖第三方库,使用ddt去做参数化
    pytest:通过装饰器@pytest.mark.parametrize来实现
    5.报告展示
    unittest:通过HTMLTestRunner生成
    pytest:可以集成allure插件生成
    6.失败重运行
    unittest:不支持
    pytest:pytest --reruns=2(2表示重运行2次)
    7.挑选用例执行
    unittest:不支持
    pytest:
    (1)创建一个pytest.ini文件,
    [pytest]
    markers = demo(标记名) : just for display(备注名,如果不写 可以不加冒号)
    (2) 在要执行的测试用例/测试类前面加上: @pytest.mark.标记名
    (3)main.py文件中添加[-m ,‘要执行用例的标签名’] 根据标签名筛选用例并执行
    8.安装需求不同
    pytest为第三方单元测试库,需额外安装;unittest为标准库,无需额外安装

    二:TestNg

    概述:TestNg是Java中的一个测试框架,可以用来做单元测试和集成测试,它可以用注解来强化测试,测试人员一般用它来进行自动化测试用例的执行。
    testng.xml文件:

    
    
    
    
     
    
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	 
        
        	
        		
    	
    	
    
    
    • 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

    (1)一个suite(套件)由一个或多个测试(test)构成
    (2)一个test(测试)是由多个类(class)组成
    (3)一个class(类)是由一个或多个方法(method)组成
    是testng.xml的根标记
    name:套件的名称,这是一个强制属性
    parallel:TestNG是否运行不同的线程来运行这个套件,默认为none,其他级别为methods、tests、classes、instances
    thread-count:如果启用并行模式(忽略其他方式),则为使用的线程数

    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.常用注解
    @BeforeMethod:注释方法将在每个测试方法之前运行
    @AfterMethod:注释方法将在每个测试方法之后运行
    @BeforeClass:在某个测试类(class)所有测试方法执行开始之前开始执行,注释方法仅运行一次
    @AfterClass:在某个测试类(class)所有测试方法执行结束之后开始执行,注释方法仅运行一次
    @BeforeTest:在某个测试(test)所有测试方法执行开始之前开始执行
    @AfterTest:在某个测试(test)所有测试方法执行结束之后开始执行
    @BeforeSuite:在某个测试套件(suite)所有测试方法执行开始之前执行
    @AfterSuite:在某个测试套件(suite)所有测试方法执行结束之后执行
    @DataProvider:数据提供者,提供数据的方法,dataProvider作为数据提供者只能返回Object[][]和Iterator类型的数据,要从该DataProvider接收数据的@Test方法需要使用与此注释名称相等的dataProvider名称
    @Parameters:描述如何将参数传递给@Test方法
    @Test:测试方法
    注意:除了@Parameters注解的方法中可以有形参,其他注解的方法均是空
    @Tes中常用的参数:
    @Test(enabled = false):用例就不会运行
    @Test(timeOut = 5000):超时测试
    @Test(groups=“group2”):分组测试
    @Test(expectedExceptions = ArithmeticException.class):预期异常测试
    @Test(dependsOnMethods= {“TestNgLearn1”}):依赖测试(硬依赖)
    分为hard依赖和soft依赖
    hard依赖:默认为此依赖方式,即其所有依赖的methods或者groups必须全部pass,否则被标识依赖的类或者方法将会被略过,在报告中标识为skip,此为默认的依赖方式;
    soft依赖:此方式下,其依赖的方法或者组有不是全部pass也不会影响被标识依赖的类或者方法的运行,注意如果使用此方式,则依赖者和被依赖者之间必须不存在成功失败的因果关系,否则会导致用例失败。此方法在注解中需要加入alwaysRun=true即可,如@Test(dependsOnMethods= {“TestNgLearn1”}, alwaysRun=true);
    2.testNg常用监听器
    IAnnotationTransformer
    IAnnotationTransformer2
    IHookable
    IInvokedMethodListener
    IMethodInterceptor
    IReporter
    ISuiteListener
    ITestListener
    3.Testng的监听器是怎么使用的?TestNg的数据驱动返回的是什么?
    Testng的监听器在自动化中的使用主要集中在失败截图和失败重试
    失败重试的需要实现两个接口IRetryAnalyzer、IAnnotationTransformer
    失败截图的需要实现ITestListener
    实现后需要在testng的配置文件中增加监听标签
    Testng的数据驱动返回结果是一个二维数组,因此在做数据驱动时,不管我们的数据是存在excel、xml
    或者数据库等存储介质中,最终我们都需要将他们转换成二维数组
    4.失败重试
    分为局部和全局
    局部:a.新建一个类FaileRetry实现IRetryAnalyzer接口,重写retry方法
    b.新建一个测试类,在测试方法中加上 @Test(retryAnalyzer = FaileRetry.class)注解
    全局:a.跟局部一样先新建一个类FaileRetry实现IRetryAnalyzer接口,重写retry方法,区别是当前正在运行的次数的变量要是公共静态的共享变量
    b.新建一个类RetryListener实现IAnnotationTransformer接口,重写transform方法,该类的作用是用来监听所有的测试方法是否有retryAnalyzer注解属性,如果有该属性则不会执行我们设定的重跑机制(局部重跑的优先级比全局的高)
    c.第一条案例失败重试次数到达最大值时,后面的案例则永远不会进入重跑机制,所以在每条案例重跑完后,需要重置当前正在运行的次数为初始值
    d.有了重试以后,发现重试执行的用例,全部记录到跳过(skipped)里面了,这样会影响我们的测试总数,测试结束后把重试的用例结果从skipped中去掉
    e.将监听类添加到testng.xml文件中
    注意点:testng版本尽量用高版本,不然可能会出现死循环等其他问题,我用6.14.3版本
    具体代码参考:https://blog.csdn.net/Caoqingqing521/article/details/110792727

    5.TestNG多线程测试时
    a、测试方法中的并发
    在测试方法上加入@Test(threadPoolSize = 5,invocationCount = 10)
    说明: threadPoolSize 表明用于调用该方法的线程池容量,该例就是同时起 5 个线程并行执行该方法;invocationCount 表示该方法总计需要被执行的次数。
    b. test, class, method级别的并发,可以通过在 testng.xml 中的 suite tag 下设置



    它们的区别如下:
    tests 级别:不同 test tag 下的用例可以在不同的线程执行,相同 test tag 下的用例只能在同一个线程中执行。
    classes 级别:不同 class tag 下的用例可以在不同的线程执行,相同 class tag 下的用例只能在同一个线程中执行。
    methods 级别:所有用例都可以在不同的线程去执
    6.参数传递方式
    a.通过parameter传参
    直接在测试方法上加上@Parameters({ “browser”, “server” }) //
    xml文件里


    b.通过dataprovider传参
    // 注解的方法必须返回一个Object[][]和Iterator类型的数据
    // 提供数据的一个测试方法。注解的方法返回一个Object[][],其中每个对象[]的测试方法的参数列表中可以分配。该@Test方法
    // 希望从这个DataProvider的接收数据,需要使用一个dataProvider名称等于这个注解名的名字
    @DataProvider(name = “user”)
    public Object[][] getstr() {
    return new Object[][] { { “admin”, “123456”, “登录成功” }, { “admin”, “12345”, “密码错误” },
    };
    }
    // DataProvider返回的是一个Object的二维数组,二维数组中的每个一维数组都会传递给调用函数,作为参数使用。运行的时候会发现
    // @Test 标识的test
    // method被执行的次数和object[][]包含的一维数组的个数是一致的,而@Test标识的函数的参数个数,也和object内一维数组内的元素数是一致的
    @Test(dataProvider = “user”)
    private void sout(String uname, String pword, String msg) {
    System.out.println(uname + “->” + pword + “->” + msg);
    }

  • 相关阅读:
    Java native关键字 实现
    Springboot 启动报错@spring.active@解析错误
    在Mysql中,什么是回表,什么是覆盖索引,索引下推?
    【Hack The Box】linux练习-- Nibbles
    二叉搜索树(Binary Search Tree,BST)
    给新手程序员的建议
    1.3 统计学习方法三要素
    对已知数组排序
    逆向分析练习六(实战CrackMe01)
    ZooKeeper 7:数据读写——原子广播协议ZAB
  • 原文地址:https://blog.csdn.net/Caoqingqing521/article/details/134305058