自动化测试框架设计-04开发pytest插件

2022-01-18 09:00:00
虫师
转贴:
公众号
2569
摘要:在上一篇文章中我们介绍了4个python单元测试框架,本章我们介绍如何开发pytest插件。

本章我们介绍如何开发pytest插件,在上一篇文章中我们介绍了4个python单元测试框架。大概分两类,一类是必须有类继承的,例如 QTAF  和 unittest , 另一类是可以没有类继承,例如nose/nose2  和 pytest 。对于没有可以没有类继承的框架,开发难度会稍大一些。

pytest扩展能力

如果我们需要给pytest增加额外的扩展能力,那么有三种方式。

1. 钩子函数

利用conftest.py  这个特殊的问题,可以创建钩子函数。

  • 目录结构:
pytest_sample/
├── conftest.py
└── test_sample.py 
                

conftest.py 文件中实现如下功能。


                    import pytest 
                    @pytest.fixture 
                    
                    def 
                    hello
                    ():     
                    return 
                    "hello 虫师" 
                

定义一个函数hello() ,并使用pytest.fixture 装饰器对其进行装饰。fixture的概念我们前面已经做介绍。这里fixture  默认的级别为function ,可以理解为被装饰的函数会在每个功能前被执行。

然后,在test_sample.py  测试文件中调动钩子函数。


                    # 调用钩子函数hello 
                    
                    def 
                    test_case
                    (hello):     print(
                    "hello:", hello)
    
                    assert hello == 
                    "hello 虫师" 
                

在测试用例中钩子函数hello() 作为测试用例的参数hello  被调用了。断言 hello 函数返回的结果是否为“hello 虫师”

  • 执行用例:

                  >
                   pytest -vs test_sample.py ================================= test session starts ===========================
collected 1 item
test_sample.py::test_case hello: hello 虫师
PASSED
================================== 1 passed in 2.61s ============================= 
              

2. 用例装饰器

我们比较常用的用例装饰是parametrize ,用法如下。


                  import pytest 
                  @pytest.mark.parametrize(     
                  'a, b', 
    [
        (
                  12),
        (
                  23),
        (
                  34),
    ]
) 
                  
                  def 
                  test_add
                  (a, b):     print(
                  f'a:
                  {a}, b:
                  {b}')
    
                  assert a + 
                  1 == b 
              

使用pytest.mark.parametrize() 装饰器,装饰test_add() 测试用例。定义a和b为参数变量,每次取一组数据进行测试。

  • 运行结果

                >
                 pytest -vs test_sample.py ================================= test session starts ===========================
collected 3 items
test_sample.py::test_add[1-2] a:1, b:2
PASSED
test_sample.py::test_add[2-3] a:2, b:3
PASSED
test_sample.py::test_add[3-4] a:3, b:4
PASSED
================================== 3 passed in 2.51s ============================= 
            

3.命令行参数

通过pytest  命令执行用例的时候作为参数传值。以pytest 的扩展插件pytest-base-url  为例。

  • 安装

              >
               pip install pytest-base-url 
          

编写用例如下:

def  test_example (base_url):

    print( "base_url:", base_url)

     assert  "http"  in base_url

这里同样用到了钩子函数base_url , 但base_url的参数定义是在执行用例的时候作为参数传入的。

  • 运行测试

            >
             pytest -vs test_sample.py --base-url https://www.baidu.com ================================= test session starts ===========================
collected 1 item
test_sample.py::test_example base_url: https://www.baidu.com
PASSED
================================== 1 passed in 2.51s ============================= 
        

pytest扩展插件

实现pytest-hello插件

我么暂且称这个插件为pytest-hello

创建pytest_hello.py 文件,实现代码如下:

import pytest



from typing  import Any, Optional







def  pytest_configure (config: Any) ->  None:


     """      register an additional marker

    """

    config.addinivalue_line(











          "markers""env(name): mark test to run only on named environment"



    )

def  pytest_runtest_setup (item: Any) ->  None:


    """


    Called to perform the setup phase for a test item.

    """

    env_names = [mark.args[ 0for mark  in item.iter_markers(name= "env")]

     if env_names:

         if item.config.getoption( "--env"not  in env_names:

            pytest.skip( "test requires env in {!r}".format(env_names))

@pytest.fixture(scope="function")

def  hello (hello_name: str) -> str:

    """

    hello Hook function

    """



     return  f"hello,  {hello_name}"

@pytest.fixture(scope="function") def  hello_name (pytestconfig: Any) -> Optional[str]:


    """

    hello_name Hook function




    """     names = pytestconfig.getoption( "--hello" )

     if len(names) ==  0:

         return  "虫师"

     if len(names) ==  1:

         return names[ 0]

     return names[ 0]







def  pytest_addoption (parser: Any) ->  None:

"""

关键字

发表评论
评论通过审核后显示。
联系我们
  • 联系人:阿道
  • 联系方式: 17762006160
  • 地址:青岛市黄岛区长江西路118号青铁广场18楼