How to modify pytest arguments?

2.4k Views Asked by At

I found out for this purpose I can use PyTest function pytest_load_initial_conftests()

https://docs.pytest.org/en/latest/example/simple.html#dynamically-adding-command-line-options

But I can't implement this example (see link) correctly.

pytest_load_initial_conftests() doesn't even start (looked through debug). Tests run ordinary without any params (one thread), but I expected "-n" param.

I installed pytest and xdist. Only two file in project. There are no pytest.ini.

What am I doing wrong? Please help run it.

conftest.py

import pytest
import os
import sys


def pytest_addoption(parser):
    parser.addoption('--some_param', action='store', help='some_param', default='')


def pytest_configure(config):
    some_param = config.getoption('--some_param')


def pytest_load_initial_conftests(args):
    if "xdist" in sys.modules:
        import multiprocessing
        num = max(multiprocessing.cpu_count() / 2, 1)
        args[:] = ["-n", str(num)] + args

test_t1.py

import inspect
from time import sleep
import os
import pytest


class Test_Run:

    def test_1(self):
        body()

    def test_2(self):
        body()

    def test_3(self):
        body()

    def test_4(self):
        body()

    def setup(self):
        pass

    def teardown(self):
        pass


def body():
    sleep(5)
2

There are 2 best solutions below

2
On

According to the docs on pytest_load_initial_conftests:

Note: This hook will not be called for conftest.py files, only for setuptools plugins.

https://docs.pytest.org/en/latest/reference/reference.html#pytest.hookspec.pytest_load_initial_conftests

Probably it shouldn't be mentioned on that page that you found.

Edit: update docs url

0
On

Add extra plugin to make pytest arguments dynamic

As per the API documentation, pytest_load_initial_conftests hook will not be called in conftest.py file and it can be used in plugins only.

Further, pytest documentation mentions how to write custom plugin for pytest and make it installable.

Following this:

create following files in root directory

- ./setup.py
- ./plugin.py
- ./tests/conftest.py
- ./pyproject.toml
# contents of ./setup.py
from setuptools import setup

setup(
    name='my_project',
    version='0.0.1',
    entry_points={
        'console_scripts': [
        ], # feel free to add if you have any
        "pytest11": ["custom_args = plugin"]
    },
    classifiers=["Framework :: Pytest"],
)

notice python11 here, it is reserved for adding pytest plugins as I have read.

# contents of ./plugin.py

import sys

def pytest_load_initial_conftests(args):
    if "xdist" in sys.modules:
        import multiprocessing
        num = max(multiprocessing.cpu_count() / 2, 1)
        args[:] = ["-n", str(num)] + args

# contents of ./tests/conftest.py

pytest_plugins = ["custom_args"] # allows to load plugin while running tests

# ... other fixtures and hooks

finally, pyproject.toml file for the project

# contents of ./pyproject.toml

[tool.setuptools]
py-modules = []

[tool.setuptools]
py-modules = []

[build-system]
requires = [
  "setuptools",
]
build-backend = "setuptools.build_meta"

[project]
name = "my_package"
description = "My package description"
readme = "README.md"
requires-python = ">=3.8"
classifiers = [
    "Framework :: Flask",
    "Programming Language :: Python :: 3",
]
dynamic = ["version"]

This will Dynamically add -n argument with value which enables parallel running based on the number of CPUs your system has.

Hope this helps, feel free to comment.