Testing Types

What Is Unit Testing? Definition, Examples & Best Practices

Posted By: Duaa Ashar Posted On:

Fixing defects gets more expensive as development progresses. Some start as small logic errors but lead to bigger issues. Fortunately, unit tests can catch these errors during development. 

This guide is for QA engineers, those transitioning from QA to automation, and QA leads.

It includes the definition of a unit test, an example of writing a unit test in Python, frameworks for unit testing, unit testing versus integration testing, best practices for unit testing and how unit testing results fit in your QA process.

What Is a Unit Test?

Unit Testing is a software testing technique used to verify individual units of source code, such as methods, functions, or classes, in isolation. It ensures that each unit behaves as expected according to its requirements. – GeeksforGeeks

A unit test focuses on one small part of the application. Developers can run it while working on the code, which makes it easier to catch mistakes before they affect other parts of the system 

A banking application, for example, uses unit tests to check interest calculations, loan eligibility rules and transaction validation logic. 

The scope of a unit test depends on the code. A failure should make the cause easy to identify. 

There are four characteristics of a good unit test:

  1. Small: It monitors one behaviour.
  2. Fast: It takes a couple of milliseconds, allowing thousands to be run on each commit.
  3. Isolated: It is not dependent on other tests, databases or external services.
  4. Repeatable: Produces the same output each time it is executed.

Developers usually write unit tests, but QA engineers can also review them. 

A unit test that indicates what the developer thinks the code should accomplish is helpful as input for designing test cases for layers above.

Imagine a car manufacturing plant. Each component is tested on a bench before being put in an engine. Unit testing does the same for software.

Why Unit Testing Matters

The benefits of unit testing all follow from one fact. Each test covers a small, isolated piece of code, so a failure has one obvious cause.

BenefitWhy It Follows From Small, Isolated Tests
Earlier defect detectionA developer runs the test seconds after writing the code, when the fix is cheapest. 
Safer refactoringA passing suite indicates that the behavior did not change after a change in code. 
Fewer regressionsExisting tests can catch bugs that return after code changes. 
Faster feedback in CI/CDA broken build is identified in a matter of minutes as long-running tests are carried out on each commit.
Living documentationA test name and its assertions describe what the code should do, and they stay current because the build fails when they drift.
Fewer defects reaching QA and productionThe logic errors are caught at the unit level, while the testers can focus on the integration and the user flows.

Failed unit tests help developers and QA identify specific issues. 

How a Unit Test Works

A unit test checks whether a function returns the expected result. 

The Arrange-Act-Assert Pattern

The Arrange-Act-Assert (AAA) pattern gives each test three steps:

  1. Arrange: Set up the inputs and any objects the unit needs.
  2. Act: Call the function or method under test.
  3. Assert: Compare the actual result with the expected result.

Keeping the steps visible makes a test easy to read and easy to debug.

A Simple Unit Test Example

This Python unit test example uses pytest and a discount calculator. One test passes and one fails. 

The first test passes because 200 minus 10% is 180.

The second test fails because the function returns -50 and raises no error. The failure shows a missing rule.

The fix is a check that raises a ValueError when the percent is above 100. This is how a unit test finds a defect before any tester sees it.

Mocks and Stubs

A unit test must stay isolated, so dependencies such as databases and APIs are replaced with test doubles.

  • Stub: Returns a fixed answer.
  • Mock: Records how it was called, so the test can verify the interaction.

Both let the unit run without the real service.

Unit Testing Techniques

Developers usually automate unit tests so they can run them again whenever the code changes. It’s possible to test individual functions manually, but that quickly becomes impractical as the codebase grows. 

White Box Testing and Code Coverage

The unit tests are white box tests. The writer reads the code and writes tests that utilize the internal paths of the code.

That’s a contrast to black box testing, in which the tester tests without looking at the code. That’s what our article on black box testing addresses.

There are two types of coverage measures that indicate the proportion of code that is executed by the tests: 

  • Statement coverage: Percentage of code lines that are executed during tests.
  • Test coverage: Percentage of branches that are executed in the tests.

Test-Driven Development (TDD)

Test-driven development (TDD) reverses the usual order. The cycle is often called red, green, refactor:

  1. Red: Write a failing test first.
  2. Green: Write the minimum code to pass it.
  3. Refactor: Clean up the code while the tests keep passing.

A unit testing framework supplies the test runner and the assertions. Most teams add a mocking library and a coverage tool next to it.

LanguageUnit Testing FrameworksMocking and Coverage Tools
JavaJUnit, TestNGMockito, JaCoCo
.NETNUnit, xUnitMoq, Coverlet
Pythonpytest, unittestunittest.mock, coverage.py
JavaScriptJest, MochaJest mocks, Sinon, Istanbul

Pick a framework that aligns with your programming language and your team’s existing ecosystem. 

For example, a Python team may find pytest easier to adopt, especially if it already fits into their CI setup. 

Unit Testing vs Integration Testing vs System Testing

Each testing level checks a different part of the application. 

Test TypeScopeSpeedTypically Written By
Unit testOne function or methodVery fastDevelopers
Integration testInteraction between componentsModerateDevelopers and QA
System testWhole applicationSlowerQA

The three levels build on each other:

  • Unit tests prove that each part works on its own.
  • Integration tests prove that the parts work together, for example, that a service reads from the database correctly.
  • System tests prove that the finished product meets its requirements.

Passing the unit test does not necessarily imply passing the integration test. Even two correct units can still fail when exchanging data in different formats. 

That is why unit testing and integration testing are a matter of level of coverage and thus require both.

The Test Pyramid

The test pyramid indicates the number of tests to write at each level. It was introduced by Mike Cohn in his book Succeeding with Agile.

  • Base: Many fast unit tests.
  • Middle: Fewer integration tests.
  • Top: A small number of slower system tests.

The shape keeps the suite fast and the feedback quick.

Unit Testing Best Practices

  • Test One Behavior Per Test: Limit each test to a single behavior. If failure happens, then it’s an issue of one thing.
  • Keep tests independent: Each test should run on its own. 
  • Name the test accordingly: test_rejects_percent_over_100 means that the test rejects percent over 100.
  • Isolate Dependencies: Mock/Stub external services or databases.
  • Test Every Commit: Ensure that the suite is part of the CI/CD process, and any change that breaks it is detected within minutes.
  • Focus on Meaningful Coverage: Start with the code that carries the most risk. A high coverage percentage means little if the tests aren’t checking whether the results are correct. `
  • Maintain your tests as carefully as your application code: When a feature changes, its tests should reflect the new behavior. Old tests that serve no purpose should be removed. 

Common Unit Testing Mistakes and Limitations

Unit tests have a defined scope, and teams run into trouble when they expect more from them.

  • Limited scope: Unit tests check individual components, so they generally won’t catch problems that only appear when services communicate or when someone uses the complete application. 
  • High coverage without good tests: A line can run during a test without any assertion checking its result.
  • Slow or flaky tests: external dependencies can cause inconsistent test results. 
  • Test implementation details: Tests tied to internal code structure may break during refactoring. Test behavior instead. 

Where Unit Tests Fit in Your QA Process

The first layer of a QA process is unit tests. They are used by the developers to test that each function works independently. QA then adds integration, system and acceptance testing to this.

Every layer has its own owner and is used for a specific purpose:

  • Unit tests: Individual functions and methods are confirmed to act as written in unit tests.
  • Integration tests: Developers and QA ensure that components exchange data correctly.
  • System and acceptance tests: QA ensures the finished product is correct.
  • Exploratory and manual tests: QA covers usability and edge cases that scripted tests usually miss.

The results of the unit tests help QA in three ways:

  • Test design: Unit tests demonstrate the developer’s expectations of each function. QA engineers can focus on integration and user flows, skipping checks that are already covered.
  • Risk assessment: If a module has thin or failing unit tests, it should be addressed more in later stages of the process.
  • Release decisions: QA leads read unit test pass rates and coverage next to other results to judge whether a build is ready. 

Typically, the results of the unit tests remain within the CI tool and QA may not have access to them. 

Teams close this gap by bringing the results into their test management tool. 

Kualitee does this with integrations for CI/CD with Jenkins, GitHub and GitLab. It displays automated test results next to manual test results and provides traceability to requirements. 

Kualitee does not run unit tests. Developers continue to run them in their own framework.

See how Kualitee connects with your CI/CD pipeline and centralizes your test results.

Frequently Asked Questions

What Is a Unit Test?
A unit test is a little piece of code (for instance, a function or method) which is tested in isolation. It executes fast and delivers the same outcome each time. This is used by developers to identify bugs early and maintain behaviour.
Who Writes Unit Tests?
Developers write unit tests usually because they understand the code and can write tests to go along with the code that they are creating. They're easy for QA's to read and are a natural place to start if you're transitioning to automation. The QA lead watches to see how things turned out to know if the build is good.
Is Unit Testing White Box or Black Box Testing?
Unit testing is white box testing. You can see the code, and so you are able to write tests for the code - for the statements, branches and paths. Black box testing tests the behaviour from outside the code. It is appropriate for system and acceptance testing.
What Is the Difference Between a Unit Test and an Integration Test?
Unit tests test a function or method in isolation. They use mocks or stubs as dependencies. Integration tests test how two or more components work together (for example, a service and a database). Unit tests are faster. Integration tests find errors between components.
What Is a Good Code Coverage Percentage?
No one value applies to every project. According to the Google Testing Blog, 60% is acceptable, 75% is commendable and 90% is exemplary. Every team will have its own goal and the value of meaningful assertions trumps the number.
Start Free Trial Elevate Software Excellence with Kualitee Top notch testing platform & one price to rule them all

Author

Duaa Ashar

Duaa is an SEO Content Writer at Kualitatem Inc., writing technical guides, B2B articles, and marketing content for enterprise QA and software testing audiences. With a business administration background and hands-on familiarity with QA methodologies, she creates content that's both technically accurate and built to rank.