Verdict
Yes
Yes, beginners should write unit tests for code that other people use, from their first task on a team: one test for each rule and boundary the change adds, with the expected value worked out by hand, run in CI on every pull request.
Why
- Blast radiususers
- Change frequencyregularly
- Detectabilityeventually
- Reversibilitywith-effort
- Test costmoderate
Yes, a beginner should write unit tests for code that other people use, because the author's experience changes none of the five factors. My typical case is a developer in their first year on a team who adds a rule to a web application, such as cleaning up phone numbers on a signup form. Blast radius is users and Change frequency is regularly, about once a month. Detectability is eventually, because a wrong rule returns a plausible value that a reviewer can miss, and Reversibility is with-effort, since saved records need a repair script. Test cost is moderate, about an hour, which a beginner spends reading the team's suite and working out the expected values by hand, so rule R11 gives Test.
| When | Decision | Why |
|---|---|---|
| The code is a course exercise that only you run and then delete | Do not test to protect the exercise; check its output against the worked examples | Blast radius falls to none: only you run the exercise and bear a failure |
| Your first public project has a few dozen users, redeploys from the repository, and stores nothing users cannot rebuild | Test minimally: one test of the main path, plus a regression test for each bug | Reversibility falls to trivial: a redeploy of the previous commit undoes the failure |
| The task changes a label or a colour that you see on screen right after the change | Do not test; look at the page before the merge | Detectability moves to immediately and Reversibility to trivial: you see the mistake, and a revert removes it |
| The rule computes a price, a discount or an invoice total | Test mandatory: every amount, the rounding and the boundary values, with a senior developer reviewing the tests | Blast radius rises to money and Reversibility to costly: a wrong charge ends in refunds |
| The code decides which user may read which record | Test mandatory: one allowed and one denied case for each role | Blast radius rises to safety-or-legal and Detectability to never: a leaked record raises no error |
What breaks if you don't test
An untested rule breaks on the input its author did not try, such as a number with a country code. The reviewer approves the change, customers meet the failure weeks later, and every record saved since the merge needs a repair script.
What you lose if you over-test
Beginners often test everything they can reach: getters, private helpers and each call a controller makes to a mock. Those tests fail on refactors that keep behaviour the same, so the beginner learns to edit tests until they pass, and coverage rises while no test checks a result a customer sees.
How to test
- Pick the rules in your change that decide a result, such as a validation, and leave glue code to the team's endpoint tests.
- Work the expected value out by hand from the ticket before you run the code.
- Copy an existing test from the team's suite and run it with pytest, JUnit 5 or the team's runner.
- Break the code once and check that the test fails.
Procedure and references
When the answer changes
- The code moves money or decides who may see a record.
- Only you run the code, as with course exercises, which stay a cheap place to practise tests.
- Your team requires a test with every change: follow the team rule.
Real incident + Code example
The phone numbers that lost their plus
On a class booking app for a chain of gyms, the first task of a junior developer on my team was normalize_phone, which cleaned up numbers from the signup form. It removed every character that was not a digit, including the plus of international numbers. I approved the pull request, because every number she had tried was local. For 19 days, 212 members saved numbers that the text message service rejected, and the rejections went to a log nobody read until a member asked why her class reminders had stopped. A script rebuilt most numbers from the signup log, and staff asked 40 members in person. The fix went in with these tests:
from members.phone import normalize_phone
def test_keeps_the_plus_of_an_international_number():
assert normalize_phone("+33 6 12 34 56 78") == "+33612345678"
def test_turns_a_leading_00_into_a_plus():
assert normalize_phone("0033 6 12 34 56 78") == "+33612345678"
def test_adds_the_country_code_to_a_local_number():
assert normalize_phone("07700 900123", country="GB") == "+447700900123"
Related questions
- Should developers write their own tests?Code under test: Yes
- Is unit testing worth it?Yes
- Should I write tests before code?Code under test: Yes
- Should I use TDD?Code under test: Yes
- Should I write tests for side projects?Yes
FAQ
- Should beginner programmers use unit testing?
Yes, beginner programmers should use unit testing on code that other people use, because a failure costs users the same whoever wrote the code. Write one test for each rule that decides a result, and run the tests in CI on every pull request.
- When should a beginner start learning unit testing?
A beginner should start learning unit testing before their first project that someone else uses, the first one where a failure has a price. Exercises are cheap practice, because each lists inputs and expected outputs, which is what a test needs.
- What should a beginner's first unit test check?
A beginner's first unit test should check one rule that decides a result, with an expected output worked out by hand. A test of a getter or of calls to a mock checks nothing a user sees. Break the code once to see the test fail.