简体   繁体   English

按自定义顺序运行 Pytest 类

[英]Run Pytest Classes in Custom Order

I am writing tests with pytest in pycharm.我正在用 pycharm 中的 pytest 编写测试。 The tests are divided into various classes.测试分为不同的类别。
I would like to specify certain classes that have to run before other classes .我想指定必须在其他类之前运行的某些类
I have seen various questions on stackoverflow (such as specifying pytest tests to run from a file and how to run a method before all other tests ).我已经看到有关 stackoverflow 的各种问题(例如指定 pytest 测试从文件运行以及如何在所有其他测试之前运行方法)。
These and various others questions wanted to choose specific functions to run in order.这些和其他各种问题都想选择特定的功能来按顺序运行。 This can be done, I understand, using fixtures or with pytest ordering .据我了解,这可以通过使用fixturespytest ordering来完成。
I don't care which functions from each class run first.我不在乎每个 class 中的哪些功能首先运行。 All I care about is that the classes run in the order I specify.我只关心这些按照我指定的顺序运行。 Is this possible?这可能吗?

Approach方法

You can use the pytest_collection_modifyitems hook to modify the order of collected tests ( items ) in place.您可以使用pytest_collection_modifyitems挂钩来修改收集的测试( items )的顺序。 This has the additional benefit of not having to install any third party libraries.这具有不必安装任何第三方库的额外好处。

With some custom logic, this allows to sort by class.使用一些自定义逻辑,这允许按 class 排序。

Full example完整示例

Say we have three test classes:假设我们有三个测试类:

  1. TestExtract
  2. TestTransform
  3. TestLoad

Say also that, by default, the test order of execution would be alphabetical, ie:还要说,默认情况下,执行的测试顺序将按字母顺序排列,即:

TestExtract -> TestLoad -> TestTransform TestExtract -> TestLoad -> TestTransform

which does not work for us due to test class interdependencies.由于测试 class 相互依赖关系,这对我们不起作用。

We can add pytest_collection_modifyitems to conftest.py as follows to enforce our desired execution order:我们可以按如下方式将pytest_collection_modifyitems添加到conftest.py以强制执行我们想要的执行顺序:

#conftest.py
def pytest_collection_modifyitems(items):
    """Modifies in place test items to execute test classes in a given order."""
    CLASS_ORDER = ["TestExtract", "TestTransform", "TestLoad"]

    # Enforce module order by iteratively pushing tests in a class to
    # the end of the execution queue
    sorted_items = items.copy()
    for class_ in CLASS_ORDER:
        items_class = [item.cls.__name__ for item in sorted_items]
        first_index = items_class.index(class_)
        last_index = len(items_class) - items_class[::-1].index(class_)
        sorted_items = (
            sorted_items[:first_index]
            + sorted_items[last_index:]
            + sorted_items[first_index:last_index]
        )
    items[:] = sorted_items

Some comments on the implementation details:关于实现细节的一些评论:

  • items_class maps the class of each item items_class映射每个item的 class
  • first_index and last_index refer to the first and last indices of items belonging to the test class under consideration first_indexlast_index指的是属于正在考虑的测试 class 的项目的第一个和最后一个索引
  • It is assumed that test classes have unique names假设测试类具有唯一的名称
  • Test classes can live in different modules测试类可以存在于不同的模块中
  • CLASS_ORDER does not have to be exhaustive. CLASS_ORDER不必详尽无遗。 You can reorder just those classes on which to want to enforce an order (but note: if reordered, any non-reordered class will execute before any reordered class)您可以仅对要强制执行订单的类重新排序(但请注意:如果重新排序,任何未重新排序的 class 将在任何重新排序的类之前执行)
  • The test order within the classes is kept unchanged类内的测试顺序保持不变
  • The sorting algorithm might not be as efficient as it could be (but honestly I have yet to find a test suite in which this could possibly matter)排序算法可能没有它应有的效率(但老实说,我还没有找到一个测试套件,这可能很重要)
  • items must be modified in place, hence the final items[:] assignment items必须就地修改,因此最终的items[:]分配

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM