The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Use Python’s standard-library unittest by subclassing unittest.TestCase, writing methods whose names begin with test, and checking behavior with assertion methods. Run the suite with python -m unittest; use python -m unittest discover when you need to control discovery directories, filename patterns, or import paths.
The unittest model
unittest organizes testing around four ideas:
- Test case: a class, usually derived from
unittest.TestCase, containing related tests. - Test method: a method whose name starts with
test. Each method should be independent and able to run alone or in any order. - Test fixture: preparation and cleanup surrounding one or more tests. The Python documentation describes a fixture as “the preparation needed to perform one or more tests.” Fixtures commonly create and remove temporary directories, databases, or server processes.
- Test runner: the command-line or programmatic component that loads tests, executes them, and reports failures.
A unit test should exercise a small piece of your own code and make a precise claim about its observable behavior. Avoid relying on another test having run first, shared mutable state, wall-clock timing, or a developer’s local files.
Write a first test, step by step
Assume this small module is saved as calculator.py:
def add(a, b):
return a + b
def divide(a, b):
if b == 0:
raise ValueError('b must not be zero')
return a / b
Create test_calculator.py in an importable location:
#1 Best Overall
import unittest
from calculator import add, divide
class CalculatorTests(unittest.TestCase):
def test_adds_integers(self):
self.assertEqual(add(2, 3), 5)
def test_divide_returns_a_float(self):
self.assertAlmostEqual(divide(5, 2), 2.5)
def test_divide_by_zero_raises(self):
with self.assertRaises(ValueError):
divide(5, 0)
if __name__ == '__main__':
unittest.main()
The imports bring in the code under test. The class groups related behavior. Every method beginning with test is collected by the runner, and assertions turn an unexpected result into a failure. The if __name__ == '__main__' block lets you run this file directly, while the same file can still be discovered by python -m unittest.
Useful assertion methods
| Assertion | Use |
|---|---|
assertEqual(actual, expected) |
Values should compare equal. |
assertNotEqual(first, second) |
Values must differ. |
assertTrue(expr) / assertFalse(expr) |
A condition should be truthy or falsey. |
assertIsNone(value) |
A function should return None. |
assertIn(member, container) |
A value should occur in a collection or string. |
assertAlmostEqual(first, second) |
Numeric results may differ by a small rounding error. |
assertRaises(ExceptionType) |
Code should raise a particular exception. |
Put the expected value in the assertion message mentally, not in a comment: a failing assertion should tell you what behavior the test requires. For floating-point calculations, prefer assertAlmostEqual rather than exact equality.
Set up and clean up fixtures safely
Use setUp before each test and tearDown afterward. This keeps tests isolated even when one test fails:
import shutil
import tempfile
import unittest
from pathlib import Path
class FileStoreTests(unittest.TestCase):
def setUp(self):
self.temp_dir = Path(tempfile.mkdtemp())
self.data_file = self.temp_dir / 'data.txt'
def tearDown(self):
shutil.rmtree(self.temp_dir, ignore_errors=True)
def test_writes_text(self):
self.data_file.write_text('hello', encoding='utf-8')
self.assertEqual(self.data_file.read_text(encoding='utf-8'), 'hello')
Creation belongs in setUp; removal belongs in tearDown. If cleanup must happen even when setup or a test raises, register it with addCleanup immediately after allocating the resource:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #2
def setUp(self):
self.temp_dir = Path(tempfile.mkdtemp())
self.addCleanup(shutil.rmtree, self.temp_dir, ignore_errors=True)
For expensive, genuinely shared preparation, setUpClass and tearDownClass run once for the class. Shared state can make tests order-dependent, so use class fixtures only when the resource is safe to share and reset between methods. A fixture that starts a local server, opens a proxy database, or creates a temporary directory should document who owns it and how it is closed.
Run one test or the whole suite
From the directory that makes your application importable, run:
python -m unittest
This starts the default discovery process. To make discovery settings explicit:
python -m unittest discover
python -m unittest discover -s tests -p 'test_*.py' -t .
-s(or--start-directory) chooses where discovery begins.-p(or--pattern) chooses the filename pattern. The documented default istest*.py.-t(or--top-level-directory) identifies the project’s top-level directory so modules can be imported consistently.
You can target a module, class, or method by its importable name:
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallpython -m unittest test_calculator
python -m unittest test_calculator.CalculatorTests
python -m unittest test_calculator.CalculatorTests.test_divide_by_zero_raises
Running a file directly (python test_calculator.py) uses the file’s unittest.main() block. Module-based commands generally produce more predictable imports in a package, so use them for repeatable local and continuous-integration runs.
How discovery and imports interact
Discovery first finds filenames, then imports those modules to inspect their tests. A file can therefore match the pattern and still fail to run if Python cannot import it. Keep the command’s working directory, package structure, and top-level path aligned.
A common layout is:
project/
app/
__init__.py
calculator.py
tests/
__init__.py
test_calculator.py
There is no single mandatory layout. What matters is that from app.calculator import add resolves in the environment where discovery runs. If your project uses a different source directory, invoke discovery with an appropriate -t value or run from the configured environment.
Import surprises can be especially confusing when an older installed copy of your package shadows the working tree. Add a temporary diagnostic to a test or a short Python command:
python -c "import app; print(app.__file__)"
The printed path should point to the checkout you intended to test. If it points into a virtual environment’s site-packages directory, install your project in editable mode using your project’s packaging workflow, adjust PYTHONPATH only for a controlled local check, or run the command from the correct top-level directory. Do not silently accept tests that import a different version of the code.
Make suites readable and deterministic
Keep tests independent
Construct fresh objects in each test, reset temporary state in fixtures, and avoid depending on execution order. A failure should identify one behavior, not a chain of earlier tests.
Use subtests for related inputs
class AddTests(unittest.TestCase):
def test_many_pairs(self):
cases = [(1, 2, 3), (0, 4, 4), (-1, 1, 0)]
for left, right, expected in cases:
with self.subTest(left=left, right=right):
self.assertEqual(add(left, right), expected)
A subtest reports which input failed while allowing the remaining cases to run.
Skip only for an explicit reason
Use @unittest.skip('reason') or a conditional skip when a test cannot run in a known environment. A skip should explain the missing dependency or platform condition; it should not hide a normal failure.
Recommended Free Tools
Best Value
Compatibility with pytest
pytest documents that it can collect and run tests written in the unittest.TestCase style. This lets a team keep existing classes while adopting pytest’s broader test-running and fixture mechanisms. Treat that as compatibility, not a universal verdict about which framework is better. Decide based on your project’s existing tests, preferred organization, plugins, and migration cost, and check the current pytest documentation because compatibility details can change between releases.
Version-sensitive command options
The commands above target the behavior documented for Python 3.11. Python’s development (main-branch) documentation also shows newer switches, including --durations for reporting slow tests. Do not add such an option to a project’s standard command until it is available in the Python versions that project supports; verify the help output for that interpreter:
python -m unittest --help
python -m unittest discover --help
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshoot failures systematically
| Symptom | Likely cause | Fix |
|---|---|---|
| “Ran 0 tests” | The file, class, or method does not match discovery naming rules. | Use a filename such as test_calculator.py, methods beginning with test, and run python -m unittest discover -s tests -p 'test*.py'. |
| “No module named …” | The start or top-level directory is not importable. | Run from the project root, set -t correctly, and verify the package path with a small import command. |
| Tests run but changes have no effect | An installed package is shadowing the checkout. | Print the imported module’s __file__; correct the environment or editable installation. |
| Cleanup errors after a failure | A resource was allocated without guaranteed cleanup. | Register addCleanup immediately after allocation or make tearDown defensive and idempotent. |
| A test passes alone but fails in the suite | Shared mutable state, leaked files, environment variables, or order dependence. | Create fresh state in setUp, remove it in cleanup, and make the test runnable in isolation. |
| Import works directly but not during discovery | Direct execution changed sys.path or the working directory. |
Prefer module execution, fix package imports, and supply explicit discovery directories. |
Performance, reliability, and cost considerations
- Unit tests are cheapest to repeat when they avoid real networks, production databases, and uncontrolled clocks. Replace external boundaries with deterministic fakes or mocks where appropriate.
- Keep slow integration checks in a separately named group or command so a quick unit-test command remains useful during development.
- Use temporary resources rather than shared developer files, and clean them even after assertion failures.
- Run the same interpreter and dependency set locally and in continuous integration; an import-path mismatch can invalidate an otherwise green result.
- When investigating a slow suite, first identify tests that perform I/O or expensive setup. Version-specific timing options such as
--durationsmust be checked against the Python release you support.
Or skip the browser setup
If your tests also need a visual capture of a web page, ScreenshotNeo provides a single HTTP request instead of maintaining browser-launch code. Its consent step accepts cookie banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers.
Using the API documented at https://screenshotneo.com/docs/:
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots, and every feature is included on every plan. Create a free ScreenshotNeo account.
Final checklist
- Does each test class inherit from
unittest.TestCase? - Do test methods start with
testand assert behavior rather than implementation details? - Can every test run alone without relying on order or leftover state?
- Are temporary resources cleaned with
tearDownoraddCleanup? - Does your discovery command use directories and patterns that match your package imports?
- Have you confirmed that tests import the checkout, not an older installed package?
- Are version-specific options verified with the Python interpreter used by the project?
Frequently Asked Questions
What is the smallest valid unittest test?
Import unittest, define a TestCase subclass with one method whose name starts with test, and include at least one assertion. Run it with python -m unittest or a direct unittest.main() block.
How do I see the exact test that failed?
Run the fully qualified module, class, or method name, for example python -m unittest test_calculator.CalculatorTests.test_divide_by_zero_raises. The runner prints the traceback and assertion details for that target.
Can unittest tests use pytest fixtures?
pytest documents support for running unittest.TestCase tests and using pytest fixtures with them. Check the current pytest documentation for release-specific behavior before changing your fixture design.
Free tools Windows power users keep installed
One-click scans. No signup required.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

