专栏首页专栏跨环境测试框架介绍-pytest的高级用法
原创

跨环境测试框架介绍-pytest的高级用法

本文将介绍针对测试和生产等不同测试环境下,维护一套可读性,追溯性强的测试用例的工具-pytest。

打开pytest.org, 第一句话就是 pytest: helps you write better programs 。 诚然,没有测试保障的程序不是好程序。在DevOps 思想流行的现进,需要有一套用于特性/bug fix 回归的测试框架和用例,能够直接被DevOps系统调用。

pytest.org有足够的的pytest的介绍,本文只会介绍如何利用pytest提供的特性支持多环境测试。

以下几个特性会在您日后的开发(测试)中遇到。

1. 标签

pytest 提供了一组内置的标签,包括

  • pytest.mark.timeout
  • pytest.mark.skipif
  • pytest.mark.xfail
  • pytest.mark.parametrize
  • pytest.mark.tryfirst
  • pytest.mark.trylast

这组标签可以直接用来修饰需要被执行的用例,使得这些用例允许在某些特定的环境下执行,标记用例的超时时间等,但另一个有用的使用方式是定义自己的marker,marker 定义在 pytest.ini 文件中。

# cat pytest.ini
[pytest]
log_cli = true
log_level = DEBUG
addopts = -p no:warnings
log_format = %(asctime)s %(levelname)s %(message)s
log_date_format = %Y-%m-%d %H:%M:%S


# custom markers

markers =
    p0test: p0 test cases: should be able run on all env
    p1test: p1 test cases: not used
    p2test: p2 only run in product env

使用 pytest --markers 可以得到当前支持的可以使用的marker。 可以方便地测试用例(方法或者类)上使用pytest 的修饰器来修改用例的执行行为:

比如如下测试类,只有变量QC_API_DEFAULT_ZONEID 的取值为100002的时候才执行。而用例test_foo 只有传递了p1test marker 的时候才执行。

import unittest
        
@pytest.mark.skipif(QC_API_DEFAULT_ZONEID != 100002, reason="only support 100002"
class TestDescribeInstances(unittest.TestCase):
    @pytest.mark.p1test
    def test_foo(self):
        assert True
        
    def test_bar(self):
        assert False
        
        

以上用例可以用以下pytest 命令执行:

pytest -v -rap -m p1test

可以通过传递环境变量,并在python代码中读取环境变量来控制这些测试用例的执行行为:

RUN_ENV=test pytest -v -rap -m p1test

2. setup 和 teardown

某些情况下,我们的测试用例需要在一个特定的场景下执行,执行完用例之后,需要把场景还原。

这时候,我们可以定义一个测试类,在这个测试类中定义 setup_class 和 tear_down 静态方法。这样就能够满足我们需要的场景,保证整个测试结束后,环境恢复原装

class ExampleTest(unittest.TestCase):

    @staticmethod
    def setup_class(cls):
        cls.foo = 1
        LOG.info("setup")

    @staticmethod
    def teardown_class(cls):
        LOG.info("teardown")

3. fixture

简单地说,当我们的测试用例需要一些“假”的数据的时候(或者测试需要具备某些前提条件),使用fixture。

@pytest.fixture(autouse=True, scope='class')
def class_client(request):

    # inject class variables
    # Notes (eliqiao): when you use it in your test function
    # do not reassign this, you can update it
    # so that we can share it in a class scope
    request.cls.inst = {}
    yield

@pytest.mark.usefixtures('class_client')
class ExampleTest(unittest.TestCase):

    @staticmethod
    def setup_class(cls):
        cls.foo = 1
        LOG.info("setup")

    @staticmethod
    def teardown_class(cls):
        LOG.info("teardown")
  

在上面的例子中,定义了一个应用在类上的fixture , 这个fixture 在这个类中的每个方法被调用之前,都会被执行,从此改变测试类的一些参数/行为。

当然,关于fixture 还有更高级的用法,如何你的测试用例需要提前准备一些数据,那么它是一个很好的选择。

4. 并行执行

通过安装 pytest-xdist (distributed testing plugin) 插件,我们可以让测试用例“并行”(在某些配置下也可以说并发)地执行测试用例,当然,是在你的系统有多个CPU或者有多个HOST可以使用的情况下。

两个关键的参数分别是:

  • -n 指定使用的 CPU 数量
  • --dist 指定并行执行测试用例的粒度。这点在测试用例有强依赖的情况下非常有用。
pytest -v -n ${WORKERS} --dist=loadfile -m $TESTFLAG --log-file ./pytest.log

5. 结合 tox

tox 是另一个能帮助我们更好地完成测试的工具。 使用 tox,能够保证测试环境的稳定性,它提供了python 的 virtualenv 环境,允许我们显式地指定我们的测试环境中需要安装哪些依赖包,从而能保证测试结果的一致性。

[testenv:py36-test]
setenv =
  LANG = en_US.utf8
  RUN_ENV = test
passenv = https_proxy QC_* QCI_*
basepython = python3.6
install_command = pip install -r requirements_dev.txt {opts} {packages}
commands = pytest {posargs:tests}

以上是一个 tox.ini 文件的片段,它定义了一个执行测试的环境,执行tox 命令,它会在执行测试之前先帮我们创建一个python的 virtualenv 的环境,在该环境中安装 requirements_dev.txt 中指定的 python 软件包(特定版本),同时传递一些环境变量到执行环境中,这些环境变量可以被 pytest 读取,然后用做 pytest 在执行marker 检查时的条件。

总结

以上,我们可以通过 tox 帮我们创建不同的测试环境,通过传递的环境变量,pytest 会选择在某些环境下运行那些测试用例。 同时这些测试用例可以并发地执行,然后输出漂亮的报告。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 聊聊 Python 的单元测试框架(三):pytest

    本篇文章是《聊聊 Python 的单元测试框架》的第三篇,前两篇分别介绍了标准库 unittest 和第三方单元测试框架 nose。作为本系列的最后一篇,压轴出...

    Python猫
  • pytest 测试框架学习(15):pytest.freeze_includes

    freeze_includes: 返回包括 cx_freeze 提供的 pytest 使用的模块名称列表。 源码:

    Mokwing
  • pytest 测试框架学习(1):初识

    3.3. 在输入框中输入 pytest 后,点击下方 Install Package,安装成功会弹出 install successfully 的提示信息。...

    Mokwing
  • Pytest系列(18)- 超美测试报告插件之allure-pytest的基础使用

    https://www.cnblogs.com/poloyy/category/1690628.html

    小菠萝测试笔记
  • PyTest运行指定的测试集

    主要有三个层级,模块、方法/函数、类,都是setup、teardown,实际写 的时候注意大小写

    苦叶子
  • pytest 测试框架学习(9):pytest.main

    pytest.main 其实 就是将 命令行执行命令使用 ide 工具在运行函数中进行了操作。

    Mokwing
  • 第八篇:《机器学习之神经网络(三)》

    每一个神经元都可以被认为是一个处理单元/神经核(processing unit/Nucleus),它含有许多输入/树突(input/Dendrite),并且有一...

    ACM算法日常
  • 为何Spring MVC可获取到方法参数名,而MyBatis却不行?【享学Spring MVC】

    Spring MVC和MyBatis作为当下最为流行的两个框架,大家平时开发中都在用。如果你往深了一步去思考,你应该会有这样的疑问:

    YourBatman
  • Hybris ECP里Customer对应的数据库表

    注册成功之后能在backoffice里看到成功生成的customer,里面的Customer ID是自动生成的,类似ABAP里的uuid.

    Jerry Wang
  • PMP-资源优化:资源平衡、资源平滑区别和举例,附对比图收藏

    资源平衡VS资源平滑:原文链接:https://www.ffeeii.com/1657.html

    yunfeiyun

扫码关注云+社区

领取腾讯云代金券