zoukankan      html  css  js  c++  java
  • 一文让你快速入门pytest框架

    pytest是什么

    官方文档描述:

    pytest is a framework that makes building simple and scalable tests easy. Tests are expressive and readable—no boilerplate code required. Get started in minutes with a small unit test or complex functional test for your application or library.

    pytest是一个python单元测试框架。

    pytest的特点

    pytest与unitest区别

    pytest用例执行

    • 使用pytest.main方法执行
    import pytest
    
    def func(x):
        return x+1
    
    def test_b():
        print('-----test_b-----')
        assert func(3)==5  # 断言失败
    
    def test_a():
        print('-----test_a-----')
        assert func(3)==4   # 断言成功
    
    if __name__=="__main__":
        pytest.main(['-s','test_demo.py'])
    
    • 使用命令行执行

    执行单个文件,进入到文件所在路径
    pytest -s test_demo.py

    执行整个目录
    pytest -s 目录名称

    pytest常用命令参数

    • 参数:-s
      运行过程中执行print打印函数:pytest -s

    • 参数:-v 或 -q
      打印用例执行的详细/简略过程,pytest -v ,pytest -q

    参考:https://www.cnblogs.com/sc912/p/11369237.html

    pytest用例前置和后置

    setup、teardown,在方法前后执行

    • pytest的setup、teardown方法可以在类之外
    import pytest
    
    
    def test_a():
        print('-----test_a-----')
    
    def test_b():
        print('-----test_b-----')
    
    def setup():
        print('-----setup-----')
    
    def teardown():
        print('-----teardown----')
    
    if __name__ == '__main__':
        if __name__ == '__main__':
            pytest.main(['-s','test_method.py'])
    

    执行结果如下:

    -----setup-----
    PASSED                                            [ 50%]-----test_a-----
    -----teardown----
    
    test_method.py::test_b -----setup-----
    PASSED                                            [100%]-----test_b-----
    -----teardown----
    
    • pytest的setup、teardown方法放在类之内
    import pytest
    
    class Test_method():
        def test_a(self):
            print('-----test_a-----')
    
        def test_b(self):
            print('-----test_b-----')
    
        def setup(self):
            print('-----setup-----')
    
        def teardown(self):
            print('-----teardown----')
    
    if __name__ == '__main__':
        if __name__ == '__main__':
            pytest.main(['-s','test_method.py'])
    

    执行结果如下:

    test_method.py::Test_method::test_b 
    
    ============================== 2 passed in 0.02s ==============================
    Process finished with exit code 0
    -----setup-----
    PASSED                               [ 50%]-----test_a-----
    -----teardown----
    -----setup-----
    PASSED                               [100%]-----test_b-----
    -----teardown----
    

    可以看到,在执行每一个方法前都会执行setup方法,在执行每个方法后都会执行teardown方法。

    setup_class、teardown_class,在类前后执行

    setup_class、teardown_class方法得放在类里面,否则不生效。

    import pytest
    
    
    class TestMethod():
        def test_a(self):
            print('-----test_a-----')
    
        def test_b(self):
            print('-----test_b-----')
    
        def setup_class(self):
            print('-----setup-----')
    
        def teardown_class(self):
            print('-----teardown----')
    
    if __name__ == '__main__':
        if __name__ == '__main__':
            pytest.main(['-s','test_class.py'])
    

    执行结果如下:

    test_class.py::TestMethod::test_a -----setup-----
    PASSED                                 [ 50%]-----test_a-----
    
    test_class.py::TestMethod::test_b PASSED                                 [100%]-----test_b-----
    -----teardown----
    

    可以看出,先执行一次setup_class,然后执行完全部方法,再执行teardown_class方法。

    import pytest
    
    
    class TestMethod():
        def test_a(self):
            print('-----test_a-----')
    
        def test_b(self):
            print('-----test_b-----')
    
        def setup(self):
            print('-----setup-----')
    
        def teardown(self):
            print('-----teardown----')
    
        def setup_class(self):
            print('-----setup_class-----')
    
        def teardown_class(self):
            print('-----teardown_class----')
    
    if __name__ == '__main__':
        if __name__ == '__main__':
            pytest.main(['-s','test_class.py'])
    

    执行结果如下:

    test_class.py::TestMethod::test_a -----setup_class-----
    -----setup-----
    PASSED                                 [ 50%]-----test_a-----
    -----teardown----
    
    test_class.py::TestMethod::test_b -----setup-----
    PASSED                                 [100%]-----test_b-----
    -----teardown----
    -----teardown_class----
    

    pytest运行规则

    默认规则

    自定义规则

    使用配置文件pytest.ini进行配置

    安装ini插件

    pycharm无法识别ini文件,需要安装插件。

    配置文件在test_pytest目录下

    指定执行test_ini目录的测试用例
    (venv) D:Testpythonhogwarts_TD est_pytest>pytest -v

    执行结果如下:

    test_ini/test_class.py::TestMethod::test_a -----setup_class-----
    -----setup-----
    -----test_a-----
    PASSED-----teardown----
    
    test_ini/test_class.py::TestMethod::test_b -----setup-----
    -----test_b-----
    PASSED-----teardown----
    -----teardown_class----
    

    注释掉指定目录后,是执行10个用例

    pytest断言

    from common.get_mysql import *
    
    def test_assert():
        a=0
        b=1
        # assert a,'断言失败打印的信息'  # 自定义断言失败打印的信息,用逗号隔开
        assert not a,'断言失败打印的信息'
        assert b,'断言失败打印的信息'
        c='c'
        d='adacde'
        e='aeewd'
        assert c in d,'断言失败打印的信息'
        assert c not in e,'断言失败打印的信息'
        
        assert a!=b
        assert a==b
        # 对比数据库数据
        assert a==get_sql("SELECT dept_no FROM departments WHERE dept_name ='Finance'")
    

    pytest标记

    是pytest特有的机制,unitest没有,作用是筛选用例。

    标记测试用例

    遇到问题:

    执行后
    (venv) D:Testpythonhogwarts_TD est_pytest>pytest -m testa

    警告:
    PytestUnknownMarkWarning: Unknown pytest.mark.testa - is this a typo?

    怎么是执行了两条用例?应该是执行一条用例才对

    似乎是与配置文件有关。

    (venv) D:Testpythonhogwarts_TD est_pytest>pytest -m "testa or testb"

    跳过测试、条件判断执行

    import pytest
    
    
    class TestMethod():
        @pytest.mark.skip
        def test_a(self):
            print('-----test_a-----')
    
        # 只执行test_b
        def test_b(self):
            print('-----test_b-----')
    
    
    if __name__ == '__main__':
        pytest.main(['-s','test_mark.py'])
    

    全部用例都不执行

    import pytest
    
    @pytest.mark.skip(reason="不要执行的用例")  # reason可以不写
    class TestMethod():
    
        def test_a(self):
            print('-----test_a-----')
    
    
        def test_b(self):
            print('-----test_b-----')
    
    
    if __name__ == '__main__':
        pytest.main(['-s','test_mark.py'])
    

    为真的时候不执行

    import pytest
    
    
    class TestMethod():
        @pytest.mark.skip(reason="不要执行的用例")  # reason可以不写
        def test_a(self):
            print('-----test_a-----')
    
        @pytest.mark.skipif(2>1,reason="不要执行的用例")  # 为真的时候不执行
        def test_b(self):
            print('-----test_b-----')
    
    
    if __name__ == '__main__':
        pytest.main(['-s','test_mark.py'])
    

    为假的时候执行用例

    import pytest
    
    
    class TestMethod():
        @pytest.mark.skip(reason="不要执行的用例")  # reason可以不写
        def test_a(self):
            print('-----test_a-----')
    
        @pytest.mark.skipif(0>1,reason="不要执行的用例")
        def test_b(self):
            print('-----test_b-----')
    
    
    if __name__ == '__main__':
        pytest.main(['-s','test_mark.py'])
    

    pytest参数化

    传入单个参数

    在测试用例的前面加上:
    @pytest.mark.parametrize("参数名",列表数据)
    参数名:用来接收每一项数据,并作为测试用例的参数。
    列表数据:一组测试数据。

    import pytest
    
    
    class TestMethod():
        @pytest.mark.parametrize('name',['xiaoming','jack'])
        def test_a(self,name):
            print('-----test_a-----')
            print(name)
    
        @pytest.mark.parametrize(('username','password'),[('xiaoming','123456'),('jacky','567890')])
        def test_b(self,username,password):
            print('-----test_b-----')
            print('username: "{}",password:"{}"'.format(username,password))
    
    
    if __name__ == '__main__':
        pytest.main(['-s','test_para.py'])
    
    

    执行结果:

    ============================== 4 passed in 0.02s ==============================
    Process finished with exit code 0
    PASSED                        [ 25%]-----test_a-----
    xiaoming
    PASSED                            [ 50%]-----test_a-----
    jack
    PASSED                 [ 75%]-----test_b-----
    username: "xiaoming",password:"123456"
    PASSED                    [100%]-----test_b-----
    username: "jacky",password:"567890"
    
    

    传入多个参数

    传入文件参数

    pytest生成报告

    修改配置文件

    以下是html报告

    pytest执行失败重试

    修改配置文件

    reruns 2,表示失败时重试2次
    delay 1,表示等待1s

  • 相关阅读:
    C算法编程题系列
    C算法编程题(七)购物
    C算法编程题(六)串的处理
    C算法编程题(五)“E”的变换
    C算法编程题(四)上三角
    C算法编程题(三)画表格
    C算法编程题(二)正螺旋
    C算法编程题(一)扑克牌发牌
    我的编程开始(C)
    T-Sql学习系列完结
  • 原文地址:https://www.cnblogs.com/Uni-Hoang/p/13290679.html
Copyright © 2011-2022 走看看