How To Write Unit Tests For Existing Python Code // Part 1 of 2

💡 Get my FREE 7-step guide to help you consistently design great software:

In this video, I show you a practical example of adding unit tests to existing code. This first part focuses on adding tests while not changing the original code. In the second part (coming out next week), I’ll show how refactoring the code simplifies test writing while also improving the design.


1) There are a few things in the test setup that are not ideal, like how dates are used in the test code, using a real API key and doing actual card charges. I’ll address these things in part 2.

2) *patching* means that you’re replacing a dependency in a function or method by something else. The thing that you replace it with is called a *mock* (apologies, my use of the terms in the video is a bit messy).

The code I worked on in this episode is available here:


🎓 Sign up to Brilliant now and get 20% off the annual subscription:

👍 If you enjoyed this content, give this video a like. If you want to watch more of my upcoming videos, consider subscribing to my channel!

💬 Discord:

👀 Code reviewers:
– Yoriz
– Ryan Laursen
– Sybren A. Stüvel
– Dale Hagglund

🎥 Video edited by Mark Bacskai:

🔖 Chapters:
0:00 Intro
1:05 Explaining the example
4:10 Analysis & Setup
6:05 Adding LineItem tests
8:40 Adding Order tests
10:56 Adding PaymentProcessor tests
15:50 Analysis of the test setup so far
17:05 Adding pay_order tests

#arjancodes #softwaredesign #python

DISCLAIMER – The links in this description might be affiliate links. If you purchase a product or service through one of those links, I may receive a small commission. There is no additional charge to you. Thanks for supporting my channel so I can continue to provide you with free content each week!


37 thoughts on “How To Write Unit Tests For Existing Python Code // Part 1 of 2”
  1. Thank you Arjan, really glad that somehow YouTube algorithms showed your channel) your content is very helpful! Nice

  2. Super interesting content. I have a question (open to anyone):

    I see that in testing with a "valid" card the expiry date is being hard coded. Would this not be a problem in the future, when the hard coded values become a "past date" and the tets are run again (and fail)? Thank you!

    PS (after watching part 2/2) My question is answered there!

  3. how do i test functions that returns unknown data? like fetching from an api? or functions that do really complex calculations and you cannot know the result before running it?

  4. Doesn't 100% (or near 100%) coverage mean you're testing every decision tree branch in your code?
    If you do that, every little change in your code requires also changing a bunch of tests along with it.
    When you really want to use tests to be able to refactor more easily, shouldn't you test *intent*?
    For example, test the output of one unit of work, so you can change the underlying implementation and have your test confirm that your new implementation still yields the same results?

  5. Hi Arjan, would be nice to know how to test very complex clases like the ones that usually appears in Deep Learning. For example, pytorch_lightning.LightningDataModule… things like the shape of tensors in several configurations, training loops, etc. I don't really know if it's worth to unit test somehow these kind of things. Currently, I'm placing asserts in my the code itself but not unit testing systematically, would be nice to know at least your point of view about this topic!

  6. 8:3010:00 Well, to be honest, it would be better if you first saw your tests fail somehow. Like maybe you could break your code intentionally, see the tests fail, and the restore.

  7. I would have also "asserted" that when the order item is created, its created with Status == OPEN

  8. Thank you for this valuable content. I have watched nearly all of your videos because I like the way you explain things. I'll start leaving comments on your videos to help the YouTube algorithm even more 🙂

  9. Honestly im so greatful for your videos.
    Im learning so much, enjoying my time and gertting alot of motivation to improve as a datascientist/developer.
    Thank you so much!!!!
    Youre awesome!

  10. 1. At 9:40, why did have only 77%? I thought all tests/ folder files will be 100% since all tests will be run by default. Anyway is there any reason to be checking for 100% coverage in files under tests/? Intuitively I would only care about coverage of the files they are testing, and not coverage of the test script itself.

    2. 14:20 def test_card_valid_date() contained no raises or assert. I thought every test would need one of these to communicate what is expected. Is this test function saying that if we can run without errors, then it passes? This feels wrong because even if it passes, it still doesn't clearly communicate the expected state, especially when there are many lines in the test function

  11. I'm so glad you've made this video, even though I don't need it anymore.

    I got a bit annoyed that there were so many Unit Test introductions, but nothing about what to do if you already have existing code, especially if said code contains a state, because all introductions have a nice, pure (meaning the function only has input and output – no sideeffects like printing text or saving files), function, which simply doesn't reflect reality.

  12. I just started delving into unit testing this week, so this video came at a perfect time!! Thank you so much, looking forward for part 2 🙂

  13. Hey Arjan, love your videos 🙂 any way you could comment on writing testable code for data science? I find it hard to write unit tests for, for example, the result of a more complex data processing function or the result of a training job.

  14. I got my first software testing job were we use pytest to automate the API testing.
    I am thankful that youtube recommended your video because i would rather learn this than watch Netflix 😀
    Thanks for putting this out for free 🙏🏽

  15. Awesome. I am from mexico Your channel is fucking great. And thanks for sharing your knowledge. Keep the good work.

  16. Thank you, this is exactly the nightmare I have to deal with. Instead of payment processors it’s expensive computations on gigabytes of data that need to be tested. Sigh. Can’t wait for part 2

  17. When I run `pytest -cov` it always says 100% but when I run coverage html it says 84% cause I intentional not fully implemented all tests

  18. 10:06 are you viewing the coverage report within vscode? I don't know how to do that – are you using a plugin? Actually getting to the coverage report is the biggest pain point in my current workflow.

  19. For the name of the test functions … It would make sense to call them [function under test]_[situation]_[expected reaction].
    So when a test fails later on, from the name of the test you can directly guess what you broke.

  20. Will the branch coverage (additional to line coverage) be in part 2?
    Can the coverage metric also be shown directly in the editor?

Leave a Reply

Your email address will not be published.

Captcha loading...