-
Notifications
You must be signed in to change notification settings - Fork 287
Guidance on constructing tests
Kalina Mincheva edited this page May 21, 2026
·
2 revisions
Tests are useful in your package for these reasons:
- If somebody changes something in the future which breaks your code, they will know and will be able to adjust the code so it doesn't.
- Tests compatibility with various versions of other packages (e.g. if you test against output of another package).
- It makes sure that your code is right (if you test with a known example from a textbook, for example).
- The code complains adequately if functions are fed wrong input.
- Recording errors in code so they do not happen again.
- Regression tests: when there's an error, and you fix it, you put in a test to ensure it doesn't happen again in the future.
assert(det(M)!=0)
- Type test: does this function give the correct type.
assert(instance(foo(x),List))
- Run test: does the code run at all?
foo(x)
-
Error test: if an error SHOULD occur on
foo(x), you can make sure that happens with:
assert(try (foo(x); false) else true)
- Unit test: just check that the output of something is something else.
assert(foo(x)==2)- Property test: checks a property of a function on an example.
QQ[x,y] I = ideal(x^2, x*y) assert(isSubset(I, radical I))
--This is a comment, write what you'd like here, like "testing dimension and degree" TEST /// R = QQ[x,y,z] assert(dim(ideal(x,y))==1) assert(degree(ideal(x,y))==1) /// --This is a second test now. TEST /// R = QQ[x,y,z] assert(dim(ideal(x,y))==1) /// --repeat these so that at least each exported function gets tested
- A test block will fail if there is any error in the block.
- Tests are implicitly numbered in the order in which they are read, starting at
mypackage.m2.
check "SumsOfSquares" -- runs all tests in the package SumsOfSquares check_3 "SumsOfSquares" -- checks the third test in the SumsOfSquares package -- capturing check(3, "SumsOfSquares") -- .197867s elapsed tests("SumsOfSquares") -- gives each test, and where it is in the code base {0 => TestInput[/usr/share/Macaulay2/SumsOfSquares.m2:1221:5-1230:3] } {1 => TestInput[/usr/share/Macaulay2/SumsOfSquares.m2:1233:5-1247:3] } {2 => TestInput[/usr/share/Macaulay2/SumsOfSquares.m2:1250:5-1261:3] } {3 => TestInput[/usr/share/Macaulay2/SumsOfSquares.m2:1264:5-1271:3] } {4 => TestInput[/usr/share/Macaulay2/SumsOfSquares.m2:1274:5-1292:3] } {5 => TestInput[/usr/share/Macaulay2/SumsOfSquares.m2:1295:5-1302:3] } {6 => TestInput[/usr/share/Macaulay2/SumsOfSquares.m2:1305:5-1347:3] } {7 => TestInput[/usr/share/Macaulay2/SumsOfSquares.m2:1350:5-1374:3] } {8 => TestInput[/usr/share/Macaulay2/SumsOfSquares.m2:1377:5-1390:3] } {9 => TestInput[/usr/share/Macaulay2/SumsOfSquares.m2:1393:5-1427:3] } {10 => TestInput[/usr/share/Macaulay2/SumsOfSquares.m2:1430:5-1434:3]} {11 => TestInput[/usr/share/Macaulay2/SumsOfSquares.m2:1437:5-1442:3]} {12 => TestInput[/usr/share/Macaulay2/SumsOfSquares.m2:1445:5-1449:3]} {13 => TestInput[/usr/share/Macaulay2/SumsOfSquares.m2:1452:5-1456:3]}
Here are common places people choose to put tests:
- In the main package file
mypackage.m2, either right after a function is defined, or all together at the end. - A common choice is putting them all at the end of the top package file.
- The recommended choice (especially for new contributors) is in a directory:
/packages/mypackage/tests.m2
and load this file in mypackage.m2. Don't forget to set AuxiliaryFiles=>true in the preamble.
- Each exported function should be tested with all options if options are available.
- Always test the trivial cases and boundary cases (what if you give the empty list? the zero ideal
<0>?<1>?). - Do not repeatedly construct the exact same object in one test block. You can use it more than once!
- Try to keep each test to a minimal time requirement (over 5s will be flagged and only allowed if necessary).
- Crucial core functions, give several tests, possibly right after defining the function.
- Sometimes
toStringis useful (orvalue(toString(x))if you are concerned about printing breaking things). - Note:
=means assignment,==checks that two things are mathematically the same,===are these the literal same object in the computer science sense:
i8 : R = QQ[x,y]; i9 : ideal(x,y) === ideal(x+y,y) o9 = false i10 : ideal(x,y) == ideal(x+y,y) o10 = true
- Test properties, not just examples! e.g.:
I = ideal(x^2, x*y) assert(isSubset(I, radical I))
- Test bad input deliberately.
- Document why non-obvious tests exist (i.e. regression tests).
- In general, it's good to have comments on why you are testing certain things.