1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
|
Configuration
=============
There are a few command line options that change the behavior of the
plugin. As with any pytest option, you can add the options to your
``pytest.ini`` if you want to have them applied to all tests automatically:
.. code::
[pytest]
; always order tests with dependency markers
addopts = --order-dependencies
.. _order-scope:
``--order-scope``
-----------------
By default, tests are ordered per session, e.g. across all modules in the
test run. Sometimes, you want to order tests per module or per test class
instead. Consider that you have a growing number of test modules that you
want to run simultaneously, with tests ordered per module. Per default you
would need to make sure that the order numbers increases globally, if you
want to run the test modules consecutively and order the test per module.
If you use the option ``--order-scope=module``, there is no need for this.
You can enumerate your tests starting with 0 or 1 in each module, and the tests
will only be ordered inside each module. Using ``--order-scope=class``
additionally considers test classes--each test class is considered
separately for ordering the tests. If a module has both test classes and
separate test functions, these test functions are handled separately from the
test classes. If a module has no test classes, the effect is the same as
if using ``--order-scope=module``.
For example consider two test modules:
**tests/test_module1.py**:
.. code::
import pytest
@pytest.mark.order(2)
def test2():
pass
@pytest.mark.order(1)
def test1():
pass
**tests/test_module2.py**:
.. code::
import pytest
@pytest.mark.order(2)
def test2():
pass
@pytest.mark.order(1)
def test1():
pass
Here is what you get using session and module-scoped sorting::
$ pytest tests -vv
============================= test session starts ==============================
...
tests/test_module1.py:9: test1 PASSED
tests/test_module2.py:9: test1 PASSED
tests/test_module1.py:5: test2 PASSED
tests/test_module2.py:5: test2 PASSED
::
$ pytest tests -vv --order-scope=module
============================= test session starts ==============================
...
tests/test_module1.py:9: test1 PASSED
tests/test_module1.py:5: test2 PASSED
tests/test_module2.py:9: test1 PASSED
tests/test_module2.py:5: test2 PASSED
``--order-scope-level``
-----------------------
This is an alternative option to define the order scope. It defines the
directory level which is used as the order scope, counting from the root
directory. The resulting scope is between the session and module
scopes defined via ``--order-scope``, where ``--order-scope-level=0`` is the
same as session scope, while setting the level to the number of test
directory levels would result in module scope.
Consider the following directory structure::
order_scope_level
feature1
__init__.py
test_a.py
test_b.py
feature2
__init__.py
test_a.py
test_b.py
with the test contents:
**test_a.py**:
.. code::
import pytest
@pytest.mark.order(4)
def test_four():
pass
@pytest.mark.order(3)
def test_three():
pass
**test_b.py**:
.. code::
import pytest
@pytest.mark.order(2)
def test_two():
pass
@pytest.mark.order(1)
def test_one():
pass
The idea here is to test each feature separately, while ordering the tests
across the test modules for each feature.
If we use session scope, we get::
$ pytest -v order_scope_level
============================= test session starts ==============================
...
order_scope_level/feature1/test_a.py::test_one PASSED
order_scope_level/feature2/test_a.py::test_one PASSED
order_scope_level/feature1/test_a.py::test_two PASSED
order_scope_level/feature2/test_a.py::test_two PASSED
order_scope_level/feature1/test_b.py::test_three PASSED
order_scope_level/feature2/test_b.py::test_three PASSED
order_scope_level/feature1/test_b.py::test_four PASSED
order_scope_level/feature2/test_b.py::test_four PASSED
which mixes the features.
Using module scope instead separates the features, but does not order the
modules as wanted::
$ pytest -v --order-scope=module order_scope_level
============================= test session starts ==============================
...
order_scope_level/feature1/test_a.py::test_three PASSED
order_scope_level/feature1/test_a.py::test_four PASSED
order_scope_level/feature1/test_b.py::test_one PASSED
order_scope_level/feature1/test_b.py::test_two PASSED
order_scope_level/feature2/test_a.py::test_three PASSED
order_scope_level/feature2/test_a.py::test_four PASSED
order_scope_level/feature2/test_b.py::test_one PASSED
order_scope_level/feature2/test_b.py::test_two PASSED
To get the wanted behavior, we can use ``--order-scope-level=2``, which keeps
the first two directory levels::
$ pytest tests -v --order-scope-level=2 order_scope_level
============================= test session starts ==============================
...
order_scope_level/feature1/test_b.py::test_one PASSED
order_scope_level/feature1/test_b.py::test_two PASSED
order_scope_level/feature1/test_a.py::test_three PASSED
order_scope_level/feature1/test_a.py::test_four PASSED
order_scope_level/feature2/test_b.py::test_one PASSED
order_scope_level/feature2/test_b.py::test_two PASSED
order_scope_level/feature2/test_a.py::test_three PASSED
order_scope_level/feature2/test_a.py::test_four PASSED
Note that using a level of 0 or 1 would cause the same result as session
scope in this example, and any level greater than 2 would emulate module scope.
``--order-group-scope``
-----------------------
This option is also related to the order scope. It defines the scope inside
which tests may be reordered. Consider you have several test modules which
you want to order, but you don't want to mix the tests of several modules
because the module setup is costly. In this case you can set the group order
scope to "module", meaning that first the tests are ordered inside each
module (the same as with the module order scope), but afterwards the modules
themselves are sorted without changing the order inside each module.
Consider these two test modules:
**tests/test_module1.py**:
.. code::
import pytest
@pytest.mark.order(2)
def test1():
pass
def test2():
pass
**tests/test_module2.py**:
.. code::
import pytest
@pytest.mark.order(1)
def test1():
pass
def test2():
pass
Here is what you get using different scopes::
$ pytest tests -vv
============================= test session starts ==============================
...
tests/test_module2.py:9: test1 PASSED
tests/test_module1.py:9: test1 PASSED
tests/test_module1.py:5: test2 PASSED
tests/test_module2.py:5: test2 PASSED
::
$ pytest tests -vv --order-scope=module
============================= test session starts ==============================
...
tests/test_module1.py:9: test1 PASSED
tests/test_module1.py:5: test2 PASSED
tests/test_module2.py:9: test1 PASSED
tests/test_module2.py:5: test2 PASSED
::
$ pytest tests -vv --order-group-scope=module
============================= test session starts ==============================
...
tests/test_module2.py:9: test1 PASSED
tests/test_module2.py:5: test2 PASSED
tests/test_module1.py:9: test1 PASSED
tests/test_module1.py:5: test2 PASSED
The ordering of the module groups is done based on the lowest
non-negative order number present in the module (e.g. the order number of
the first test). If only negative numbers are present, the highest negative
number (e.g. the number of the last test) is used, and these modules will be
ordered at the end. Modules without order numbers will be sorted between
modules with a non-negative order number and modules with a negative order
number, the same way tests are sorted inside a module.
The group order scope defaults to the order scope. In this case the tests are
ordered the same way as without the group order scope. The setting takes effect
only if the scope is less than the order scope, e.g. there are three
possibilities:
- order scope "session", order group scope "module" - this is shown in the
example above: first tests in each module are ordered, afterwards the modules
- order scope "module", order group scope "class" - first orders tests inside
each class, then the classes inside each module
- order scope "session", order group scope "class" - first orders tests inside
each class, then the classes inside each module, and finally the modules
relatively to each other
This option will also work with relative markers, and with dependency markers
if using the :ref:`order-dependencies` option.
Here is a similar example using relative markers:
**tests/test_module1.py**:
.. code::
import pytest
@pytest.mark.order(after="test_module2.py::test1")
def test1():
pass
def test2():
pass
**tests/test_module2.py**:
.. code::
import pytest
def test1():
pass
@pytest.mark.order(before="test1")
def test2():
pass
Here is what you get using different scopes::
$ pytest tests -vv
============================= test session starts ==============================
...
tests/test_module1.py:5: test2 PASSED
tests/test_module2.py:9: test1 PASSED
tests/test_module2.py:5: test2 PASSED
tests/test_module1.py:9: test1 PASSED
::
$ pytest tests -vv --order-group-scope=module
============================= test session starts ==============================
...
tests/test_module2.py:9: test1 PASSED
tests/test_module2.py:5: test2 PASSED
tests/test_module1.py:9: test1 PASSED
tests/test_module1.py:5: test2 PASSED
You can see that in the second run the second test module is run before the
first because of the dependency, but the tests inside each module remain in
the same order as before. Note that using module scope as in the example
above doesn't make sense here due to the dependencies between modules.
This will also work with dependency markers if using the
:ref:`order-dependencies` option.
.. note::
This option will not work together well with the sparse ordering option.
.. _order-dependencies:
``--order-dependencies``
------------------------
This defines the behavior if the `pytest-dependency`_ plugin is used.
By default, ``dependency`` marks are only considered if they coexist with an
``order`` mark. In this case it is checked if the ordering would break the
dependency, and is ignored if this is the case. Consider the following:
.. code:: python
import pytest
def test_a():
assert True
@pytest.mark.dependency(depends=["test_a"])
@pytest.mark.order("first")
def test_b():
assert True
In this case, the ordering would break the dependency and is therefore
ignored. This behavior is independent of the option. Now consider the
following tests:
.. code:: python
import pytest
@pytest.mark.dependency(depends=["test_b"])
def test_a():
assert True
@pytest.mark.dependency
def test_b():
assert True
By default, ``test_a`` is not run, because it depends on ``test_b``, which
is only run after ``test_b``::
$ pytest tests -vv
============================= test session starts ==============================
...
test_dep.py::test_a SKIPPED
test_dep.py::test_b PASSED
If you use ``--order-dependencies``, this will change--the tests will now be
reordered according to the dependency and both run::
$ pytest tests -vv --order-dependencies
============================= test session starts ==============================
...
test_dep.py::test_b PASSED
test_dep.py::test_a PASSED
Note that a similar feature may be added to ``pytest-dependency`` -
if this is done, this option will not be needed, but for the time being you
can use both plugins together to get this behavior.
Note that ``pytest-order`` does not replace ``pytest-dependency``--it just
adds ordering to the existing functionality if needed.
.. note::
``pytest-dependency`` also has the possibility to `add dependencies at
runtime`_ using ``pytest_dependency.depends``. These dependencies cannot be
detected at collection time and therefore are not included in ordering.
The same is true for the `dynamic compilation of marked parameters`_.
.. _order-marker-prefix:
``--order-marker-prefix``
-------------------------
Consider the following: You have several groups of tests where you want to decide
which test groups to execute in a certain test run. This is usually done using custom markers,
so that you can filter the tests by the markers using the "-m" option:
.. code:: python
import pytest
@pytest.mark.m3
def test_a():
assert True
@pytest.mark.m1
def test_b():
assert True
@pytest.mark.m2
def test_c():
assert True
Running these you get::
$ pytest tests -vv -m "m2 or m3"
============================= test session starts ==============================
...
test_module.py:5: test_a PASSED
test_module.py:15: test_c PASSED
Now consider that the test groups shall always be executed in a certain order, e.g.
the group with the marker "m1" shall always be executed before the tests with "m2" etc.
This can be achieved by adding an additional order marker to each test:
.. code:: python
import pytest
@pytest.mark.order(3)
@pytest.mark.m3
def test_a():
assert True
@pytest.mark.order(1)
@pytest.mark.m1
def test_b():
assert True
etc. Running these you get the desired order::
$ pytest tests -vv -m "m2 or m3"
============================= test session starts ==============================
...
test_module.py:18: test_c PASSED
test_module.py:6: test_a PASSED
This looks redundant and is also error-prone. If you want to order them instead
just using your own marker (which has the order index already in the name), you can use
the option ``--order-marker-prefix``. Running the original tests without any order marker
gives you now::
$ pytest tests -vv -m "m2 or m3" --order-marker-prefix=m
============================= test session starts ==============================
...
test_module.py:18: test_c PASSED
test_module.py:6: test_a PASSED
.. note::
As usually, you are responsible for registering your own markers, either in the
code or in the ``pytest.ini`` file. If you forget this, pytest will give you warnings about unknown markers.
.. _indulgent-ordering:
``--indulgent-ordering``
------------------------
You may sometimes find that you want to suggest an ordering of tests, while
allowing it to be overridden for good reason. For example, if you run your test
suite in parallel and have a number of tests which are particularly slow, it
might be desirable to start those tests running first, in order to optimize
your completion time. You can use the ``pytest-order`` plugin to inform pytest
of this.
Now suppose you also want to prioritize tests which failed during the
previous run, by using the ``--failed-first`` option. By default,
pytest-order will override the ``--failed-first`` order, but by adding the
``--indulgent-ordering`` option, you can ask pytest to run the sort from
pytest-order *before* the sort from ``--failed-first``, allowing the failed
tests to be sorted to the front (note that in pytest versions from 6.0 on,
this seems not to be needed anymore, at least in this specific case).
.. _sparse-ordering:
``--sparse-ordering``
---------------------
Ordering tests by ordinals where some numbers are missing by default behaves
the same as if the the ordinals are consecutive. For example, these tests:
.. code:: python
import pytest
@pytest.mark.order(3)
def test_two():
assert True
def test_three():
assert True
def test_four():
assert True
@pytest.mark.order(1)
def test_one():
assert True
are executed in the same order as:
.. code:: python
import pytest
@pytest.mark.order(1)
def test_two():
assert True
def test_three():
assert True
def test_four():
assert True
@pytest.mark.order(0)
def test_one():
assert True
e.g. you get::
$ pytest tests -vv
============================= test session starts ==============================
...
test_module.py:13: test_one PASSED
test_module.py:3: test_two PASSED
test_module.py:6: test_three PASSED
test_module.py:9: test_four PASSED
The gaps between numbers, and the fact that the starting number is not 0,
are ignored. This is consistent with the current behavior of
``pytest-ordering``.
If you use the ``--sparse-ordering`` option, the behavior will change::
$ pytest tests -vv --sparse-ordering
============================= test session starts ==============================
...
test_module.py:6: test_three PASSED
test_module.py:13: test_one PASSED
test_module.py:9: test_four PASSED
test_module.py:3: test_two PASSED
Now all missing numbers (starting with 0) are filled with unordered tests, as
long as unordered tests are left. In the shown example, ``test_three``
is filled in for the missing number 0, and ``test_four`` is filled in for the
missing number 2. This will also work for tests with negative order numbers
(or the respective names). The missing ordinals are filled with unordered
tests first from the start, then from the end if there are negative numbers,
and the rest will be in between (e.g. between positive and negative numbers),
as it is without this option.
``--error-on-failed-ordering``
------------------------------
Relative ordering of tests my fail under some circumstances. Mostly this happens if the related marker
is not found, or if the tests have a cyclic dependency.
The default behavior in this case is not to order the test in question, issue a warning during test
collection and execute the test as usual. If you want to make sure that your relative markers work
without checking all warning messages, you can also make the tests that cannot be ordered fail, so that
they show up as errored in the report:
.. code:: python
import pytest
def test_one():
assert True
@pytest.mark.order(before="test_three")
def test_two():
assert True
In this example, the test "test_three" on which "test_two" depends, does not exist.
If you use the option `--error-on-failed-ordering`, "test_two" will now error:
$ pytest tests -vv --error-on-failed-ordering
============================= test session starts ==============================
...
WARNING: cannot execute 'test_two' relative to others: 'test_three'
test_failed_ordering.py::test_one PASSED
test_failed_ordering.py::test_two ERROR
=================================== ERRORS ====================================
__________________________ ERROR at setup of test_two__________________________
...
=========================== short test summary info ===========================
ERROR test_failed_ordering.py::test_two - Failed: The test could not be ordered
========================= 1 passed, 1 error in 0.75s ==========================
.. _`pytest-dependency`: https://pypi.org/project/pytest-dependency/
.. _`dynamic compilation of marked parameters`: https://pytest-dependency.readthedocs.io/en/stable/advanced.html#dynamic-compilation-of-marked-parameters
.. _`add dependencies at runtime`: https://pytest-dependency.readthedocs.io/en/stable/usage.html#marking-dependencies-at-runtime
|