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

    15
    37



    💡 Get my FREE 7-step guide to help you consistently design great software: https://arjancodes.com/designguide.

    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.

    NOTES:

    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: https://github.com/ArjanCodes/2022-test-existing-code.

    🛒 GEAR & RECOMMENDED BOOKS: https://kit.co/arjancodes.

    🎓 Sign up to Brilliant now and get 20% off the annual subscription: https://brilliant.sjv.io/arjancodes.

    👍 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: https://discord.arjancodes.com
    🐦Twitter: https://twitter.com/arjancodes
    🌍LinkedIn: https://www.linkedin.com/company/arjancodes
    🕵Facebook: https://www.facebook.com/arjancodes

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

    🎥 Video edited by Mark Bacskai: https://www.instagram.com/bacskaimark

    🔖 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!

    source

    Previous articleGetting started with Ansible 13 – Adding Users & Bootstrapping
    Next articleVMWare Workstation Pro شرح تفصيلى لبرنامج صناعة الاجهزة الافتراضية

    37 COMMENTS

    1. 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!

    2. 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?

    3. 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!

    4. 1. At 9:40, why did test_order.py 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

    5. 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.