Skip to content

lib.tests.modules: create nix-unit test scaffolding #381342

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

adisbladis
Copy link
Member

@adisbladis adisbladis commented Feb 12, 2025

Things done

Together with @hsjobeki at thaigersprint

EDIT by @hsjobeki together with @infinisil :

Plan to move on:

  • Make some kind of nix-unit 2.3 (if feasible)
    • Alternative: Automatically emit shell/python/... code to test against nix cli 2.3
  • Integrate the tests into the CI:
    • lib/tests/release.nix
  • Rebase & Update to also include the latest tests.

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandboxing enabled in nix.conf? (See Nix manual)
    • sandbox = relaxed
    • sandbox = true
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 25.05 Release Notes (or backporting 24.11 and 25.05 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

Add a 👍 reaction to pull requests you find important.

cc Thaigersprint/thaigersprint-2025#1

@adisbladis adisbladis marked this pull request as draft February 12, 2025 03:30
@github-actions github-actions bot added 6.topic: module system About "NixOS" module system internals 6.topic: lib The Nixpkgs function library labels Feb 12, 2025
@nix-owners nix-owners bot requested review from roberth and infinisil February 12, 2025 03:31
@github-actions github-actions bot added 10.rebuild-darwin: 1 This PR causes 1 package to rebuild on Darwin. 10.rebuild-darwin: 1-10 This PR causes between 1 and 10 packages to rebuild on Darwin. 10.rebuild-linux: 1 This PR causes 1 package to rebuild on Linux. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. labels Feb 12, 2025
@hsjobeki
Copy link
Contributor

hsjobeki commented Feb 12, 2025

I'd like to provide some insights why we think using nix-unit is better than using the current lib/tests/modules.sh
And better than lib.runTest

  • much faster (estimate some factor ~100).
  • allows to load the test for debugging into the nix repl as it is just an attribute set.
  • allows to organize tests in nested attribute sets.
  • Allows to also assert on the error type not only the message.
  • Expressions don't need to be matched as string.

Those and further benefits can also be found on the project page: https://github.com/nix-community/nix-unit

@roberth
Copy link
Member

roberth commented Feb 12, 2025

We currently run the suite against multiple Nix versions. If we have a pairing of nix-unit for each of them, I suppose we can continue to do so.

allows to load the test for debugging into the nix repl as it is just an attribute set.

Does that include intermediate values, like the whole evalModules result for example?
In the example, it seems that the only exposed values are the ones that are compared.

@roberth
Copy link
Member

roberth commented Feb 12, 2025

Another thing is that in the test suite we often use the same module for multiple assertions.
I suppose a let binding could help with that, and I would be inclined to model this pattern as:

# group for a specific but large module
intTypes =
  let
    inherit (evalModules ...) config;
  in
    {
      # test cases for each assertion
      negativeInt = ... config.negativeInt ...;
    };

Now I'm not sure that this is even the right pattern, as it's probably better to keep the test cases small and focused, so I guess that's something to pay attention to.
I don't think we'd want to "mechanically" translate the whole thing without cleaning it up.
But doing that is also risky, because the intent of the test may not always be clear, and therefore, mistakes can be made when shrinking the context of an assertion, making the assertion ineffective or less effective by not failing.
So I guess we do want a mechanical translation anyway, certainly at first.
Test cases can be refactored later when someone dives into the subject and thoroughly understands the intricacies.

@roberth
Copy link
Member

roberth commented Feb 12, 2025

a pairing of nix-unit for each of them

This could be done by having version conditionals using nix.version in the nix-unit package function.
Even src could be conditional. This way we don't have to add multi-version support upstream with CPP conditionals.

That way the existing lib/tests/release.nix stuff can create nix-units by calling nix-unit.override { inherit nix; }.

@hsjobeki
Copy link
Contributor

hsjobeki commented Feb 13, 2025

I just pushed a commit with all tests translated. While doing so i didn't change any of the tests although there where about 10 that had minor discrepancies in the regex behavior. We can see that translation is relatively trivial and that the result is absolutely identical. Despite we lack the ability for now to test against different nix versions.

/nixpkgs/lib/tests/modules/ > time nix-unit tests.nix > /dev/null
warning: unknown setting 'allowed-users'
warning: unknown setting 'trusted-users'
warning: `--gc-roots-dir' not specified
trace: { a = "one"; b = "two"; class = { just = "data"; }; meta = "meta"; }
nix-unit tests.nix > /dev/null  0,12s user 0,02s system 94% cpu 0,152 total
/nixpkgs/lib/tests/modules/ > time sh ../modules.sh
====== module tests ======
262 Pass
0 Fail
sh ../modules.sh  4,77s user 2,32s system 104% cpu 6,822 total

Pros:

  • Debugging is easy (thus writing tests is easy)
  • Organizing tests is easy.
  • Speed: execution time is very fast
  • Utility to provide coverage feedback exists
  • Simple: Eval test are plain nix. No bash wrapper required.

Cons:

  • Uses a static nix version currently
  • Code becomes longer

Maybe we can find a suitable way of providing nix-unit with more than one nix version.
Q: Which versions do we need to support ?

@infinisil
Copy link
Member

Q: Which versions do we need to support ?

3 of them are currently being tested:

nixVersions ? [ pkgs-nixVersions.minimum nix pkgs-nixVersions.latest ],

I think this is really neat overall, but testing with multiple Nix versions is fairly important. However I think it would be fine to drop nixVersions.minimum (2.3), because that version is mainly just needed to allow evaluating Nixpkgs to upgrade Nix itself.

@roberth
Copy link
Member

roberth commented Feb 13, 2025

@infinisil looking at the bigger picture, don't we want to use this infrastructure for all of lib's unit tests?
I also doubt that the minimum version shouldn't apply to NixOS, which uses the module system.
I guess it may be possible as a user to wiggle out of such a situation by first updating the nix client, with nix-shell -p, but this would be annoying and not at all obvious to users, even if they are few on 2.3.

Relatedly, we should certainly add the NixOS-stable default version as well. I believe that might currently coincide with nix, so we might be ok on that for now.

@nixpkgs-ci nixpkgs-ci bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Aug 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md 6.topic: lib The Nixpkgs function library 6.topic: module system About "NixOS" module system internals 10.rebuild-darwin: 1-10 This PR causes between 1 and 10 packages to rebuild on Darwin. 10.rebuild-darwin: 1 This PR causes 1 package to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. 10.rebuild-linux: 1 This PR causes 1 package to rebuild on Linux.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants