Skip to content

Commit 25aa38a

Browse files
authored
feat(tests): add test-lib (tlib) (#439)
1 parent d0f0d0d commit 25aa38a

5 files changed

Lines changed: 456 additions & 37 deletions

File tree

CONTRIBUTING.md

Lines changed: 104 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Adding Modules!
1+
## Adding Modules!
22

33
There are 2 kinds of modules in this repository. One kind which defines the `package` option, and one kind which does not.
44

@@ -121,78 +121,146 @@ Example:
121121
}
122122
```
123123

124-
# Formatting
124+
## Formatting
125125

126126
`nix fmt`
127127

128-
# Tests
128+
## Tests
129129

130130
`nix flake check -Lv ./ci`
131131

132-
# Run Site Generator Locally
132+
## Run Site Generator Locally
133133

134134
`nix run ./ci`
135135

136136
or
137137

138138
`nix run ./ci#docs`
139139

140-
# Writing tests
140+
To run the tests for an individual wrapper only, run
141+
142+
`nix build ./ci#checks.{system}.wrapperModule-{name}`
143+
144+
Example (neovim on `x86_64-linux`):
145+
146+
`nix build ./ci#checks.x86_64-linux.wrapperModule-neovim`
147+
148+
## Writing Tests
141149

142150
You may also include a `check.nix` file in your module's directory.
143151

144-
It will be called via `pkgs.callPackage`, provided with the flake `self` value.
145-
(i.e. `pkgs.callPackage your_check.nix { inherit self; }`)
152+
It will be called via `pkgs.callPackage`, provided with the flake `self` value, as well as a test-library `tlib` value.
153+
(i.e. `pkgs.callPackage your_check.nix { inherit self tlib; }`)
146154

147-
It should build a derivation which tests the wrapper derivation as best you can.
148155

149-
If a command fails, it fails the test. If it builds the derivation successfully, it passes the test.
156+
We provide a testing library `tlib` that provides an easy-to-use interface to write tests.
150157

151-
If the program gives options for running the program to check the generated configuration is correct, you should do that.
158+
### Writing Tests for Wrappers
152159

153-
Sometimes it is not easily possible to run the program within a derivation, in those cases, searching the wrapper derivation and other generated files and their contents is also acceptable.
160+
If you are writing tests for a wrapper module, it is important to pass the name
161+
of the wrapper to the first argument of the `test` function like in the example
162+
below (marked at `(*)`). By doing this, we can grab the specified `wrapper.meta.platforms` config
163+
of the wrapper (if any) and ensure that the tests are only run on the required platforms.
154164

155-
Example:
156165

157166
```nix
158167
{
159168
pkgs,
160-
runCommand,
161169
self,
170+
tlib,
171+
...
162172
}:
173+
163174
let
164-
gitWrapped = self.wrappers.git.wrap {
165-
inherit pkgs;
166-
settings = {
167-
user = {
168-
name = "Test User";
169-
email = "test@example.com";
175+
inherit (tlib)
176+
fileContains
177+
isDirectory
178+
isFile
179+
notIsFile
180+
areEqual
181+
test
182+
;
183+
in
184+
test { wrapper = "direnv"; } { # <-- Specify the name of the wrapper here (*)
185+
186+
"direnv wrapper should be created" =
187+
let
188+
wrapper = self.wrappers.direnv.wrap {
189+
inherit pkgs;
190+
nix-direnv.enable = true;
170191
};
171-
};
192+
in
193+
[
194+
"[[ -d ${wrapper} ]]" # <-- a simple condition to be asserted
195+
{
196+
cond = "[[ -d ${wrapper} ]]";
197+
msg = "No directory found for wrapper."; # <-- you can also specify a custom error message
198+
}
199+
(isDirectory wrapper) # <-- or use pre-defined helpers
200+
];
201+
202+
"wrapper should output correct version" =
203+
let
204+
wrapper = self.wrappers.direnv.wrap {
205+
inherit pkgs;
206+
};
207+
in
208+
'' # <-- no need to provide a list if there is only one assertion
209+
"${wrapper}/bin/direnv" --version |
210+
grep -q "${wrapper.version}"
211+
'';
212+
213+
"math-tests" = { # <-- tests can be arbitrarily grouped
214+
addition = [
215+
(areEqual 2 (1 + 1))
216+
(areEqual 7 (5 + 2))
217+
];
218+
multiplication = [
219+
(areEqual 1 (1 * 1))
220+
(areEqual 10 (5 * 2))
221+
];
172222
};
173-
in
174-
runCommand "git-test" { } ''
175-
"${gitWrapped}/bin/git" config user.name | grep -q "Test User"
176-
"${gitWrapped}/bin/git" config user.email | grep -q "test@example.com"
177-
touch $out
178-
''
223+
}
179224
```
180225

181-
If your module declares a list of valid platforms via its `meta.platforms` option, you should disable your test on the relevant platforms like so:
226+
227+
Pre-defined assertions like `isDirectory` or `areEqual` are already available in tlib.
228+
Feel free to contribute more if you find new ones that other maintainers might benefit from.
229+
230+
### Writing Tests for Helper Modules or Library Functions
231+
232+
The syntax is identical to [the example above](#writing-tests-for-wrappers),
233+
except you don't provide a wrapper but a name:
182234

183235
```nix
184-
if builtins.elem pkgs.stdenv.hostPlatform.system self.wrappers.waybar.meta.platforms then
185-
pkgs.runCommand "waybar-test" { } ''
186-
"${waybarWrapped}/bin/waybar" --version | grep -q "${waybarWrapped.version}"
187-
touch $out
188-
''
189-
else
190-
null
236+
{
237+
pkgs,
238+
self,
239+
tlib,
240+
...
241+
}:
242+
243+
let
244+
inherit (tlib)
245+
fileContains
246+
isDirectory
247+
isFile
248+
notIsFile
249+
areEqual
250+
test
251+
;
252+
in
253+
test "my-test" { # <-- Specify an arbitrary name for your test
254+
# test { name = "my-test" } { # <-- This is equivalent
255+
256+
"my first test" = [ ... ]; # <-- nothing new here
257+
"my second test" = [ ... ];
258+
}
191259
```
192260

193261
If you are writing a helper module, or something very complex, you may wish to have multiple derivations. Simply return a set of them instead.
194262

195-
# Commit Messages
263+
## Commit Messages
196264

197265
Changes to wrapper modules should be titled `<type>(wrapperModules.<name>): some description`.
198266
For new additions, the description should be `init`, with any further explanation on subsequent lines
@@ -212,6 +280,6 @@ For everything else, do the best you can to follow conventional commit message s
212280

213281
Why specify this? I was having trouble figuring out what to title my commits. So now I know.
214282

215-
# Questions?
283+
## Questions?
216284

217285
The [github discussions board](https://github.com/BirdeeHub/nix-wrapper-modules/discussions) is open and a great place to find help!

ci/docs/default.nix

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,23 @@ in
208208
src = "${placeholder "generated"}/wrapper_docs/${n}.md";
209209
}) (builtins.attrNames config.drv.wrapper_docs);
210210
}
211+
{
212+
name = "Contributing";
213+
data = "numbered";
214+
path = "md/CONTRIBUTING.md";
215+
src = ../../CONTRIBUTING.md;
216+
subchapters = [
217+
{
218+
name = "tlib";
219+
data = "numbered";
220+
path = "tlib.md";
221+
src = "${placeholder "out"}/wrappers-lib/tlib.md";
222+
build = ''
223+
${pkgs.nixdoc}/bin/nixdoc --category "" --description 'Testing library `tlib` documentation' --file '${../test-lib.nix}' --prefix "tlib" >> $out/wrappers-lib/tlib.md
224+
'';
225+
}
226+
];
227+
}
211228
];
212229
};
213230
}

ci/flake.nix

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
inherit system;
2121
config.allowUnfree = true;
2222
};
23+
tlib = pkgs.callPackage ./test-lib.nix { inherit self; };
2324

2425
# Load checks from ci/checks/ directory
2526
coreAndCiChecks = lib.pipe ./checks [
@@ -43,7 +44,7 @@
4344
name = "${prefix}-${name}";
4445
inherit value;
4546
};
46-
result = pkgs.callPackage value { inherit self; };
47+
result = pkgs.callPackage value { inherit self tlib; };
4748
in
4849
if result == null then
4950
[ ]

0 commit comments

Comments
 (0)