自动化测试框架之Pytest

Posted HT . WANG

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自动化测试框架之Pytest相关的知识,希望对你有一定的参考价值。

基于python的自动化测试框架:

  • unittest  (白盒单元测试)
  • pytest(白盒单元测试)
  • robotframework (系统测试)

pytest 可以用来做 系统测试 的自动化, 它的特点有

  • 用 Python 编写测试用例,简便易用

  • 可以用 文件系统目录层次 对应 手工测试用例 层次结构

  • 灵活的 初始化清除 机制

  • 可以灵活挑选测试用例执行

  • 利用第三方插件,可以生成不错的报表

pytest测试用例

class Test_错误密码:

    def test_C001001(self):
        print('\\n用例C001001')
        assert 1 == 1
        
    def test_C001002(self):
        print('\\n用例C001002')
        assert 2 == 2
        
    def test_C001003(self):
        print('\\n用例C001003')
        assert 3 == 2

(1)要求编写测试用例代码文件 必须以 test_ 开头,或者以 _test 结尾

(2)如果我们把测试用例存放在类中, 类名必须以 Test 为前缀的  ,用例对应的方法必须以 test 为前缀的方法

(3)测试用例代码执行命令:pytest

  • 如果我们希望 显示测试代码中print的内容,因为这些打印语句在调试代码时很有用,可以加上命令行参数 -s
pytest -s
  • 如果我们希望得到更详细的执行信息,包括每个测试类、测试函数的名字,可以加上参数 -v,这个参数可以和 -s 合并为 -sv
pytest -sv

(4)产生测试报告

        安装pytest-html插件

pip install pytest-html

        产生报告

pytest cases --html=report.html --self-contained-html

初始化清除

  • 模块级别

模块级别 的初始化、清除 分别 在整个模块的测试用例 执行前后执行,并且 只会执行1次 

def setup_module():
    print('\\n *** 初始化-模块 ***')


def teardown_module():
    print('\\n ***   清除-模块 ***')

class Test_错误密码:

    def test_C001001(self):
        print('\\n用例C001001')
        assert 1 == 1
        
    def test_C001002(self):
        print('\\n用例C001002')
        assert 2 == 2
        
    def test_C001003(self):
        print('\\n用例C001003')
        assert 3 == 2


class Test_错误密码2:

    def test_C001021(self):
        print('\\n用例C001021')
        assert 1 == 1
        
    def test_C001022(self):
        print('\\n用例C001022')
        assert 2 == 2

执行命令 pytest cases -s ,运行结果如下

collected 5 items

cases\\登录\\test_错误登录.py
 *** 初始化-模块 ***

用例C001001
.
用例C001002
.
用例C001003
F
用例C001021
.
用例C001022
.
 ***   清除-模块 ***
  • 类级别

类级别 的初始化、清除 分别 在整个类的测试用例 执行前后执行,并且 只会执行1次

def setup_module():
    print('\\n *** 初始化-模块 ***')

def teardown_module():
    print('\\n ***   清除-模块 ***')

class Test_错误密码:

    @classmethod
    def setup_class(cls):
        print('\\n === 初始化-类 ===')

    @classmethod
    def teardown_class(cls):
        print('\\n === 清除 - 类 ===')
        
    def test_C001001(self):
        print('\\n用例C001001')
        assert 1 == 1
        
    def test_C001002(self):
        print('\\n用例C001002')
        assert 2 == 2
        
    def test_C001003(self):
        print('\\n用例C001003')
        assert 3 == 2

class Test_错误密码2:

    def test_C001021(self):
        print('\\n用例C001021')
        assert 1 == 1
        
    def test_C001022(self):
        print('\\n用例C001022')
        assert 2 == 2

执行命令 pytest cases -s ,运行结果如下

collected 5 items

cases\\登录\\test_错误登录.py
 *** 初始化-模块 ***

 === 初始化-类 ===

用例C001001
.
用例C001002
.
用例C001003
F
 === 清除 - 类 ===

用例C001021
.
用例C001022
.
 ***   清除-模块 ***
  • 方法级别

方法级别 的初始化、清除 分别 在类的 每个测试方法 执行前后执行,并且 每个用例分别执行1次

def setup_module():
    print('\\n *** 初始化-模块 ***')

def teardown_module():
    print('\\n ***   清除-模块 ***')

class Test_错误密码:

    @classmethod
    def setup_class(cls):
        print('\\n === 初始化-类 ===')

    @classmethod
    def teardown_class(cls):
        print('\\n === 清除 - 类 ===')
        
    def setup_method(self):
        print('\\n --- 初始化-方法  ---')

    def teardown_method(self):
        print('\\n --- 清除  -方法 ---')
        
    def test_C001001(self):
        print('\\n用例C001001')
        assert 1 == 1
        
    def test_C001002(self):
        print('\\n用例C001002')
        assert 2 == 2
        
    def test_C001003(self):
        print('\\n用例C001003')
        assert 3 == 2

class Test_错误密码2:

    def test_C001021(self):
        print('\\n用例C001021')
        assert 1 == 1
        
    def test_C001022(self):
        print('\\n用例C001022')
        assert 2 == 2

执行命令 pytest cases -s ,运行结果如下

collected 5 items

cases\\登录\\test_错误登录.py
 *** 初始化-模块 ***

 === 初始化-类 ===

 --- 初始化-方法  ---

用例C001001
.
 --- 清除  -方法 ---

 --- 初始化-方法  ---

用例C001002
.
 --- 清除  -方法 ---

 --- 初始化-方法  ---

用例C001003
F
 --- 清除  -方法 ---

 === 清除 - 类 ===

用例C001021
.
用例C001022
.
 ***   清除-模块 ***

挑选测试用例执行

  • 指定一个模块
pytest cases\\登录\\test_错误登录.py
  • 指定目录

        指定一个目录

pytest cases

        指定多个目录

pytest cases1  cases2\\登录
  • 指定一个类
pytest cases\\登录\\test_错误登录.py::Test_错误密码
  • 指定一个类方法
pytest cases\\登录\\test_错误登录.py::Test_错误密码::test_C001001
  • 根据函数名字
pytest -k C001001 -s

注意,-k 后面的名字

  • 可以是测试函数的名字,可以是类的名字,可以是模块文件名,可以是目录的名字

  • 是大小写敏感的

  • 不一定要完整,只要能有部分匹配上就行

  • 可以用 not 表示选择名字中不包含,比如

    pytest -k "not C001001" -s
    
  • 可以用 and 表示选择名字同时包含多个关键字,比如

    pytest -k "错 and 密码2" -s
    
  • 可以用 or 表示选择名字 包含指定关键字之一即可,比如

    pytest -k "错 or 密码2" -s

数据驱动

如果有一批测试用例,具有 相同的测试步骤 ,只是 测试参数数据不同 。

自动化测试时,把测试数据从用例代码中 分离 开来,以后增加新的测试用例,只需要修改数据。

class Test_错误登录:
    @pytest.mark.parametrize('username, password, expectedalert', [
        (None, '88888888', '请输入用户名'),
        ('byhy', None, '请输入密码'),
        ('byh', '88888888', '登录失败 : 用户名或者密码错误'),
        ('byhy', '8888888', '登录失败 : 用户名或者密码错误'),
        ('byhy', '888888888', '登录失败 : 用户名或者密码错误'),
    ]
                             )
    def test_UI_0001_0005(self, username, password, expectedalert):
        alertText = loginAndCheck(username, password)
        assert alertText == expectedalert

用例 UI-0001 到 UI-0005 这5个登录的测试用例,共同的特点是,它们测试步骤是一模一样的,只是输入的数据(用户名、密码)不同,要检查的输出数据(错误提示)不同。

以上是关于自动化测试框架之Pytest的主要内容,如果未能解决你的问题,请参考以下文章

pytest接口自动化测试框架 | pytest之fixture介绍

Python自动化测试框架之unittest和pytest

软件测试框架之unittest与pytest的对比-

Python接口自动化测试之pytest与unittest区别

Python接口自动化测试之pytest与unittest区别

Web 自动化测试全面提升之 Pytest