Unit Testing
Unit testing checks one small, observable behavior automatically, with the code and its dependencies controlled so failures point to a clear rule. It gives you fast feedback before broader integration tests exercise real systems.
itSoftware engineering | OpenSkills.info
Course pathWalk it in order
Look it upDip in anytime
Go furtherLeaves this page
Don't Panic
Don't Panic: Unit Testing
Unit testing is a small automatic argument with your code: given this known situation, does this one behavior still keep its promise? It exists because checking everything by clicking through an application is slow, vague, and has an unfortunate tendency to discover defects only after lunch.
The central trick is Arrange, Act, Assert. Arrange the smallest useful setup. Act once on the behavior. Assert the result a caller can observe. That result might be a returned value, a state change, a handled error, or a charge request sent to another component. The test runner delivers the verdict, which is kinder than recruiting a human to interpret a wall of output.
The other crucial idea is the unit boundary, the part of the system kept under control for this check. A database, network call, filesystem, clock, or random source can answer a different question from the one you meant to ask. That does not make those things villains. It means they belong in integration tests when the real seam is the risk. Unit tests are fast evidence for component rules, not ceremonial proof that the whole application has achieved enlightenment.
Controlled collaborators are called test doubles. A stub returns prepared data. A fake is a small working replacement. A mock verifies a required interaction. The surprising part is that a mock is not automatically more thorough. If callers care about a value, assert the value. If the contract requires one charge request, assert that request. Recording every private helper call merely teaches the test the current plumbing diagram, which is very loyal until the plumbing changes.
Coverage is another number with a job and a tendency to be asked to do someone else's job. It reports executed code. It cannot tell whether an assertion matters or whether the risky behavior is missing. A flaky result has a similarly awkward message: something outside the intended behavior is still in charge. Control time, randomness, order, and asynchronous completion instead of retrying the ambiguity into submission.
Read the Intro for the full boundary and test-double map. Use Slides when you want the relationships compressed into decisions. Keep the Cheatsheet nearby while writing a test, then take the exercise when one approval rule needs a proper, observable contract. The quiz checks whether the vocabulary has stopped behaving like a crowd of suspiciously similar acronyms.
Where this skill leads
Relevant careers
See how this topic contributes to broader role-level skill maps.
Sources
- https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-best-practices
Supports
- Unit tests can be fast, isolated, repeatable, self-checking, and timely
- Unit tests should avoid infrastructure dependencies such as databases and filesystems
- Arrange, Act, Assert separates setup, execution, and expected result
- Tests should focus on observable public behavior rather than private implementation
- Coverage does not by itself establish code quality
- Controlling static time dependencies makes tests repeatable
- https://docs.junit.org/current/user-guide/
Supports
- JUnit is a current framework reference for test methods, assertions, parameterized tests, lifecycle, and execution
- https://learn.microsoft.com/en-us/dotnet/core/testing/
Supports
- The .NET testing overview connects test concepts with a platform and frameworks
- https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-code-coverage
Supports
- Code coverage measures code exercised by tests and requires interpretation alongside test quality
- https://github.com/TheJambo/awesome-testing
Supports
- The curated list identifies WireMock as an open-source HTTP mock engine
- The curated list identifies Bruno as an open-source API client for exploring and testing APIs
- https://github.com/junit-team/junit-framework/wiki/JUnit-Java-Baselines
Supports
- JUnit 0, 3, 4, and 5 mark documented Java testing-framework baselines from 1997 through 2017
- JUnit 4 uses annotations and JUnit 5 uses a Java 8 baseline with lambda-based dynamic tests
- https://docs.pytest.org/en/stable/history.html
Supports
- py.test took shape in 2004 and pytest history documents its fixtures and plugin architecture in 2009
- https://docs.pytest.org/en/latest/changelog.html
Supports
- pytest 2.0 was released as a separate package in November 2010
- https://martinfowler.com/articles/mocksArentStubs.html
Supports
- Stubs support state verification and mocks support behavior verification
- https://testing.googleblog.com/2021/03/test-flakiness-one-of-main-challenges.html
Supports
- Arbitrary delays can make tests slower and flaky over time
- https://vitest.dev/guide/why.html
Supports
- Vitest is designed as a Vite-native test runner
- https://docs.pytest.org/en/stable/contents.html
Supports
- pytest documents assertion writing, test invocation, and test discovery
- https://jestjs.io/
Supports
- Jest provides isolated JavaScript test processes and assertion tooling
- https://nunit.org/
Supports
- NUnit is an open-source unit-testing framework for .NET languages
- https://xunit.net/
Supports
- xUnit.net is an open-source unit-testing tool for .NET
