Skip to main content
v2026.11,858 entries · CC-BY 4.0

What Is Unit Testing? Examples in Python and R

Unit testing explained with runnable pytest, unittest and testthat examples, exact commands, and how to read a failing test report.

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

  1. Install pytest with pip install -U pytest.
  2. Create a file named test_sample.py containing 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
  3. Run pytest from the folder that contains the file.
  4. Read the report (next section), then change the expected value to 4 and run again to see the test pass.

Python with the standard-library unittest

  1. Create a test class that inherits from unittest.TestCase and give each test a method whose name starts with test. 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()
  2. Run a module with python -m unittest test_module1 test_module2, one class with python -m unittest test_module.TestClass, or one method with python -m unittest test_module.TestClass.test_method. Running with no arguments starts test discovery.

R with testthat

  1. Install the package with install.packages("testthat").
  2. Inside an R package directory, run usethis::use_test("name") to create a test file.
  3. 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 test on classes that inherit from unittest.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 == 5 pattern: 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) or pytest.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)

Related CASRAI pages: reproducibility, SPSS syntax for reproducible analysis.

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about What Is Unit Testing? Examples in Python and R

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Ask CASRAI · Regulatory Radar

Research-admin question? Get an answer that links its sources.

An AI assistant specialized in research administration. Every answer links its sources to check before you act. 2 questions free, no account. $29/month after.

  • Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.
  • Every answer numbers its sources and links each one, so you can check the source yourself.