Written and maintained by CASRAI Editorial Board
Last updated
Unit testing is the practice of writing small automated checks, each of which tests one specific behaviour of your code against a known input and expected result. In the words of the Python documentation, a test case is “the individual unit of testing” and it “checks for a specific response to a particular set of inputs.” You write the checks once, run them whenever the code changes, and read a pass or fail report instead of re-checking results by hand.
This page uses two documented ecosystems for analysis code, Python (unittest and pytest) and R (testthat), and shows the exact commands and the output you should expect, taken from each project’s own documentation.
What unit testing is used for in research
Analysis scripts and research packages change over time: a column is renamed, a cleaning step is added, a function is refactored. A unit test records what a function is supposed to return for a given input, so a later change that breaks that behaviour shows up as a failed test instead of a silently different result. The testthat project puts the motivation this way: “Testing your code can be painful and tedious, but it greatly increases the quality of your code.”
Tests are also what an automated build runs. If your project uses continuous integration, the test command shown below is the kind of command such a pipeline executes on every change. Unit tests also support the wider goal of computational reproducibility, because they document and check the behaviour of the code that produces your results.
Vocabulary you will see in any framework
The Python unittest documentation defines four terms that carry over to most testing frameworks’ output and manuals:
| Term | Definition (Python unittest documentation) |
|---|---|
| Test case | “the individual unit of testing. It checks for a specific response to a particular set of inputs.” In unittest it is the base class TestCase. |
| Test fixture | “the preparation needed to perform one or more tests, and any associated cleanup actions.” |
| Test suite | “a collection of test cases, test suites, or both.” |
| Test runner | “orchestrates the execution of tests and provides the outcome to the user.” |
Install or access (official sources only)
- unittest (Python): documented as part of the Python standard library at docs.python.org/3/library/unittest.html. It was originally inspired by JUnit and supports test automation, shared setup and shutdown code, grouping tests into collections, and independence of the tests from the reporting framework.
- pytest (Python):
pip install -U pytest, per the pytest Getting Started guide. - testthat (R):
install.packages("testthat"), per the testthat website.
Step-by-step: write and run a first test
Python with pytest
- Install pytest with
pip install -U pytest. - Create a file named
test_sample.pycontaining a function and a test (this is the pytest documentation’s own example; the test is deliberately wrong so you can see a failure):def func(x): return x + 1 def test_answer(): assert func(3) == 5 - Run
pytestfrom the folder that contains the file. - Read the report (next section), then change the expected value to
4and run again to see the test pass.
Python with the standard-library unittest
- Create a test class that inherits from
unittest.TestCaseand give each test a method whose name starts withtest. The Python documentation’s example:import unittest class TestStringMethods(unittest.TestCase): def test_upper(self): self.assertEqual('foo'.upper(), 'FOO') def test_isupper(self): self.assertTrue('FOO'.isupper()) self.assertFalse('Foo'.isupper()) def test_split(self): s = 'hello world' self.assertEqual(s.split(), ['hello', 'world']) # check that s.split fails when the separator is not a string with self.assertRaises(TypeError): s.split(2) if __name__ == '__main__': unittest.main() - Run a module with
python -m unittest test_module1 test_module2, one class withpython -m unittest test_module.TestClass, or one method withpython -m unittest test_module.TestClass.test_method. Running with no arguments starts test discovery.
R with testthat
- Install the package with
install.packages("testthat"). - Inside an R package directory, run
usethis::use_test("name")to create a test file. - Write your expectations in that file, then run
devtools::test()to run all the tests in the package.
Output and how to read it
When the deliberately wrong pytest example above runs, the pytest documentation shows a failure line of the form FAILED test_sample.py::test_answer - assert 4 == 5 and a summary of 1 failed in 0.12s. Read it from left to right: the file, the test function that failed, then the comparison that did not hold, where the left side (4) is what the code returned and the right side (5) is what the test expected. The [100%] marker shown while tests run refers to overall progress through all test cases, not to the share that passed.
To test that code fails correctly, both frameworks have a form for expected errors. In unittest it is with self.assertRaises(TypeError):, shown above. In pytest it is with pytest.raises(SystemExit):, and a passing run of such a file with pytest -q test_sysexit.py reports 1 passed in 0.12s.
The unittest documentation lists many assertion methods beyond assertEqual, including assertNotEqual, assertTrue, assertFalse, assertIs, assertIsNone, assertIn, assertIsInstance, assertAlmostEqual, assertGreater, assertLess, assertRegex and assertCountEqual. assertAlmostEqual is the one to look at first when a test compares computed numbers.
Troubleshooting
- No tests were run. unittest looks for methods whose names begin with
teston classes that inherit fromunittest.TestCase; with no command-line arguments it starts test discovery. Check that your test names and base class follow that pattern. - Only part of the suite should run. Name the module, class or method on the command line, as shown in the unittest steps above, or name the file for pytest (for example
pytest -q test_sysexit.py). - A failure line shows two values. Use the
assert 4 == 5pattern: first value is what the code produced, second is what the test expected. Decide whether the code or the expectation is wrong. - An error path needs testing. Wrap the call in
assertRaises(unittest) orpytest.raises(pytest).
Frameworks by language
| Framework | Language | Install or access | Run all tests |
|---|---|---|---|
| unittest | Python | Python standard library (documentation at docs.python.org) | python -m unittest (no arguments starts discovery) |
| pytest | Python | pip install -U pytest |
pytest |
| testthat | R | install.packages("testthat") |
devtools::test() inside a package |
For more on analysis tooling in this area, see sharing a reproducible conda environment, which covers recreating the software environment your tests run in.
FAQ
What is unit testing in simple terms?
It is writing a small automated check for one specific behaviour of your code, with a known input and an expected result, so that running the check tells you immediately whether that behaviour still holds.
What is a unit test case?
The Python documentation defines it as the individual unit of testing: it checks for a specific response to a particular set of inputs.
What is the difference between a test case and a test suite?
A test case is one check. A test suite is, in the unittest documentation’s words, a collection of test cases, test suites, or both.
How do I run unit tests in Python?
With pytest, install it using pip install -U pytest and run pytest. With unittest, run python -m unittest followed by a module, class or method name, or with no arguments to start discovery.
How do I run unit tests in R?
Install testthat with install.packages("testthat"), create a test file with usethis::use_test("name") from a package directory, and run devtools::test() to run every test in the package.
Sources (official documentation)
- Python Software Foundation, unittest, Unit testing framework: https://docs.python.org/3/library/unittest.html (checked 2026-10-29).
- pytest documentation, Get Started: https://docs.pytest.org/en/stable/getting-started.html (checked 2026-10-29).
- testthat: https://testthat.r-lib.org/ (checked 2026-10-29).
Related CASRAI pages: reproducibility, SPSS syntax for reproducible analysis.








