Home Explore Blog CI



nixpkgs

17th chunk of `doc/languages-frameworks/python.section.md`
3fde66fc04e7046941db94dbe4c0cdbf35352f5f8c182c9a0000000100000fb0
To use `pytestCheckHook`, add it to `nativeCheckInputs`.
Adding `pytest` is not required, since it is included with `pytestCheckHook`.

```nix
{
  nativeCheckInputs = [
    pytestCheckHook
  ];
}
```

`pytestCheckHook` recognizes the following attributes:

`enabledTestPaths` and `disabledTestPaths`

:   To specify path globs (files or directories) or test items.

`enabledTests` and `disabledTests`

:   To specify keywords for class names or test method names.

`enabledTestMarks` and `disabledTestMarks`

:   To specify test marks.

`pytestFlags`

:   To append additional command-line arguments to `pytest`.

By default, `pytest` automatically discovers which tests to run.
If tests are explicitly enabled, only those tests will run.
A test, that is both enabled and disabled, will not run.

The following example demonstrates usage of various `pytestCheckHook` attributes:

```nix
{
  nativeCheckInputs = [
    pytestCheckHook
  ];

  # Allow running the following test paths and test objects.
  enabledTestPaths = [
    # Find tests under the tests directory.
    # The trailing slash is not necessary.
    "tests/"

    # Additionally run test_foo
    "other-tests/test_foo.py::Foo::test_foo"
  ];

  # Override the above-enabled test paths and test objects.
  disabledTestPaths = [
    # Tests under tests/integration requires additional data.
    "tests/integration"
  ];

  # Allow tests by keywords matching their class names or method names.
  enabledTests = [
    # pytest by default only runs test methods begin with "test_" or end with "_test".
    # This includes all functions whose name contains "test".
    "test"
  ];

  # Override the above-enabled tests by keywords matching their class names or method names.
  disabledTests = [
    # Tests touching networks.
    "upload"
    "download"
  ];

  # Additional pytest flags
  pytestFlags = [
    # Disable benchmarks and run benchmarking tests only once.
    "--benchmark-disable"
  ];
}
```

These attributes are all passed into the derivation directly
and added to the `pytest` command without additional Bash expansion.
It requires `__structuredAttrs = true` to pass list elements containing spaces.

The `<enabled/disabled>TestsPaths` attributes expand Unix-style globs.
If a test path contains characters like `*`, `?`, `[`, or `]`, you can
quote them with square brackets (`[*]`, `[?]`, `[[]`, and `[]]`) to match literally.

The `<enabled/disabled>Tests` and `<enabled/disabled>TestMarks` attribute pairs
form a logical expression `((included_element1) or (included_element2)) and not (excluded_element1) and not (excluded_element2)`
which will be passed to pytest's `-k` and `-m` flags respectively.
With `__structuredAttrs = true` enabled, they additionally support sub-expressions.

For example, you could disable test items like `TestFoo::test_bar_functionality`
by disabling tests that match both `"Foo"` **and** `"bar"`:

```nix
{
  __structuredAttrs = true;

  disabledTests = [
    "Foo and bar"
  ];
}
```

The main benefits of using `pytestCheckHook` to construct `pytest` commands
is structuralization and eval-time accessibility.
This is especially helpful to select tests or specify flags conditionally:

```nix
{
  disabledTests =
    [
      # touches network
      "download"
      "update"
    ]
    ++ lib.optionals (pythonAtLeast "3.8") [
      # broken due to python3.8 async changes
      "async"
    ]
    ++ lib.optionals stdenv.buildPlatform.isDarwin [
      # can fail when building with other packages
      "socket"
    ];
}
```

#### Using pythonImportsCheck {#using-pythonimportscheck}

Although unit tests are highly preferred to validate correctness of a package, not
all packages have test suites that can be run easily, and some have none at all.
To help ensure the package still works, [`pythonImportsCheck`](#using-pythonimportscheck) can attempt to import
the listed modules.

```nix
{
  pythonImportsCheck = [
    "requests"
    "urllib"
  ];
}
```

roughly translates to:

```nix
{
  postCheck = ''

Title: Detailed Usage of pytestCheckHook and pythonImportsCheck
Summary
This section gives a detailed explanation of using `pytestCheckHook` with code examples showcasing attributes like `enabledTestPaths`, `disabledTestPaths`, `enabledTests`, `disabledTests`, `enabledTestMarks`, `disabledTestMarks`, and `pytestFlags`. It also covers how to handle globbing characters, create logical expressions for test selection, and conditionally select tests based on Python version or platform. Finally, it introduces `pythonImportsCheck` as a method to ensure a package works by attempting to import listed modules, especially when proper test suites are absent.