============ Contributing ============ .. default-role:: code .. include:: rstcommon.rst .. contents:: Contributing happens via "Pull requests" (PR) on github. Every PR needs to be reviewed before it can be merged and the Continuous Integration should be green. The PR has to be approved by two core developers or by Araq. Writing tests ============= There are 4 types of tests: 1. `runnableExamples` documentation comment tests, ran by `nim doc mymod.nim`:cmd: These end up in documentation and ensure documentation stays in sync with code. 2. separate test files, e.g.: ``tests/stdlib/tos.nim``. In nim repo, `testament`:cmd: (see below) runs all ``$nim/tests/*/t*.nim`` test files; for nimble packages, see https://github.com/nim-lang/nimble#tests. 3. (deprecated) tests in `when isMainModule:` block, ran by `nim r mymod.nim`:cmd:. `nimble test`:cmd: can run those in nimble packages when specified in a `task "test"`. 4. (not preferred) ``.. code-block:: nim`` RST snippets; these should only be used in rst sources, in nim sources `runnableExamples` should now always be preferred to those for several reasons (cleaner syntax, syntax highlights, batched testing, and parameter `rdoccmd` allows customization). Not all the tests follow the convention here, feel free to change the ones that don't. Always leave the code cleaner than you found it. Stdlib ------ Each stdlib module (anything under ``lib/``, e.g. ``lib/pure/os.nim``) should preferably have a corresponding separate test file, e.g. ``tests/stdlib/tos.nim``. The old convention was to add a `when isMainModule:` block in the source file, which only gets executed when the tester is building the file. Each test should be in a separate `block:` statement, such that each has its own scope. Use boolean conditions and `doAssert` for the testing by itself, don't rely on echo statements or similar; in particular, avoid things like `echo "done"`. Don't use `unittest.suite` and `unittest.test`. Sample test: .. code-block:: nim block: # foo doAssert foo(1) == 10 block: # bug #1234 static: doAssert 1+1 == 2 block: # bug #1235 var seq2D = newSeqWith(4, newSeq[bool](2)) seq2D[0][0] = true seq2D[1][0] = true seq2D[0][1] = true doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]] # doAssert with `not` can now be done as follows: doAssert not (1 == 2) Always refer to a GitHub issue using the following exact syntax: ``bug #1234`` as shown above, so that it's consistent and easier to search or for tooling. Some browser extensions (e.g. https://github.com/sindresorhus/refined-github) will even turn those in clickable links when it works. Rationale for using a separate test file instead of `when isMainModule:` block: * allows custom compiler flags or testing options (see details below) * faster CI since they can be joined in ``megatest`` (combined into a single test) * avoids making the parser do un-necessary work when a source file is merely imported * avoids mixing source and test code when reporting line of code statistics or code coverage Compiler -------- The tests for the compiler use a testing tool called `testament`:cmd:. They are all located in ``tests/`` (e.g.: ``tests/destructor/tdestructor3.nim``). Each test has its own file. All test files are prefixed with `t`. If you want to create a file for import into another test only, use the prefix `m`. At the beginning of every test is the expected behavior of the test. Possible keys are: - `cmd`: A compilation command template e.g. `nim $target --threads:on $options $file`:cmd: - `output`: The expected output (stdout + stderr), most likely via `echo` - `exitcode`: Exit code of the test (via `exit(number)`) - `errormsg`: The
discard """
file: "tblock1.nim"
line: 14
errormsg: "undeclared identifier: \'ha\'"
"""
# check for forward label and
# for failure when label is not declared
proc main =
block endLess:
write(stdout, "Muaahh!\N")
break endLess
break ha #ERROR
main()