pytest-order

repository·main·Indexed 42 days ago

https://github.com/pytest-dev/pytest-order

A pytest plugin to customize the execution order of tests using markers or configuration options. It supports index-based, relative, and scope-based ordering (session, module, class, or directory). Key features include hierarchical grouping, integration with pytest-dependency, sparse ordering, and options to handle ordering failures as errors or abort the test run.

Tokens
7.8K
Snippets
27
Records
42
Agent score
51%

What's inside pytest-order

  1. Overview of pytest-order features

    main

    The pytest-order plugin provides several ways to control test execution flow:

    • Index-based ordering: Use ordinal numbers (including negative indices) to position tests.
    • Relative ordering: Use before and after marker attributes to define relationships between specific tests.
    • Scope-based ordering: Control ordering at the session, module, class, or directory levels using configuration options like order-scope and order-scope-level.
    • Hierarchical ordering: Use order-group-scope for module and class-level grouping.
    • Dependency integration: Order tests alongside pytest-dependency markers using the order-dependencies option.
    • Sparse ordering: Use the sparse-ordering option to manage non-contiguous test sequences.
    • Custom marker prefixes: Use the order-marker-prefix option to change the default marker name.
  2. What is the difference between pytest-order and pytest-ordering?

    main

    pytest-order is a fork of the unmaintained pytest-ordering project. They are not compatible because pytest-order changed the marker name and removed other special markers for consistency.

    If you are migrating from pytest-ordering, use the following mapping:

    pytest-ordering markerpytest-order equivalent
    @pytest.mark.order1@pytest.mark.order(1)
    @pytest.mark.run(order=1)@pytest.mark.order(1)
    @pytest.mark.first@pytest.mark.order("first")
  3. Use multiple order markers to run a test multiple times

    main

    If you apply more than one @pytest.mark.order marker to a single test, the test will be executed multiple times. Each marker creates a unique ParameterSet. This allows you to combine absolute ordering (using integers) and relative ordering (using before or after) in a single test definition.

    When markers are combined, the test runs once for every marker provided, following the combined logic of all markers.

    import pytest
    
    @pytest.mark.order(1)
    @pytest.mark.order(-1)
    def test_one_and_seven():
        pass
    
    @pytest.mark.order(2)
    @pytest.mark.order(-2)
    def test_two_and_six():
        pass
    
    def test_four():
        pass
    
    @pytest.mark.order(before="test_four")
    @pytest.mark.order(after="test_four")
    def test_three_and_five():
        pass
  4. Default behavior for unordered tests

    main

    By default, tests without an @pytest.mark.order marker are executed:

    1. After all tests with positive ordinal numbers (or their string equivalents).
    2. Before all tests with negative ordinal numbers.

    Within the group of unordered tests, their relative execution order is not changed.

  5. Order tests at the class level

    main

    Applying @pytest.mark.order to a class reorders the entire class as a single unit relative to other tests or classes, but does not change the internal execution order of the tests within that class.

    import pytest
    
    @pytest.mark.order(1)
    class Test1:
        def test_1(self):
            assert True
        def test_2(self):
            assert True
    
    @pytest.mark.order(0)
    class Test2:
        def test_1(self):
            assert True
        def test_2(self):
            assert True
  6. Using pytest-order with pytest-randomly

    main

    When pytest-randomly is installed, it executes tests in a random order. pytest-order is executed after pytest-randomly (unless using --indulgent-ordering), meaning your marked tests will follow the specified order, but all other unordered tests will remain in a random sequence.

    This is a useful strategy for preventing hidden test dependencies: you can explicitly order known dependent tests while letting the rest run randomly.

    To explicitly disable pytest-randomly for a specific run, use the -p no:randomly flag.

    python -m pytest -p no:randomly
  7. How absolute and relative ordering interact

    main

    When combining absolute (ordinal) and relative (before/after) markers, relative ordering takes precedence.

    If a relative constraint conflicts with an ordinal index, the plugin will adjust the ordinal position to satisfy the relative requirement. This applies to transitive chains of relative constraints as well, which are resolved into a single globally consistent order.

    import pytest
    
    # test_second will run BEFORE test_first because of the 'after' constraint,
    # even though test_first has a lower ordinal index.
    @pytest.mark.order(index=0, after="test_second")
    def test_first():
        assert True
    
    @pytest.mark.order(1)
    def test_second():
        assert True
  8. Using pytest-order with pytest-xdist

    main

    By default, pytest-xdist schedules tests in an unordered fashion, which breaks the execution order configured by pytest-order.

    To preserve test ordering when using pytest-xdist, you must:

    1. Group all dependent tests into the same file.
    2. Run pytest with the --dist=loadfile option. This ensures all tests from a single file are executed in the same worker thread.
    python -m pytest --dist=loadfile
  9. Order tests using ordinal numbers or strings

    main

    You can define an absolute execution order using the @pytest.mark.order marker. You can use either integers (the short form) or the index keyword (the long form). Negative numbers work like Python list indices, counting from the end.

    Ordinal Strings: For convenience, you can use names like "first", "last", etc., which map to specific integers. These are only defined for the first and last 8 positions.

    import pytest
    
    # Using short form (integers)
    @pytest.mark.order(1)
    def test_one():
        assert True
    
    # Using long form (index keyword)
    @pytest.mark.order(index=-1)
    def test_four():
        assert True
    
    # Using ordinal strings
    @pytest.mark.order("first")
    def test_one_alt():
        assert True
    
    @pytest.mark.order("last")
    def test_last_alt():
        assert True
  10. Combine pytest-order with pytest-dependency

    main

    If you need both test ordering and dependency management (skipping tests that depend on failed/skipped tests), you can use both pytest-order and pytest-dependency together.

    To ensure that pytest-order respects the dependencies defined by pytest-dependency, use the --order-dependencies option. Note that only static dependency markers are considered for ordering.

    python -m pytest --order-dependencies
  11. Order entire test modules using pytestmark

    main

    To order the execution of entire modules (e.g., for workflow steps where modules depend on each other), define a pytestmark variable at the module level. This applies the order marker to every test within that module.

    Ordering Logic for Modules:

    1. Modules with an order marker $\ge 0$ are executed first in ascending order.
    2. Modules without any order markers are executed next (in their default order).
    3. Modules with a negative order marker are executed last.

    Tests within a module that share the same order marker will maintain their original relative order.

    import pytest
    
    # This applies to all tests in this module
    pytestmark = pytest.mark.order(1)
    
    
    def test_1():
        ...
    
    
    def test_2():
        ...