Unit Testing in Python
Key Takeaways
This video by NeuralNine covers unit testing in Python, a crucial skill for ensuring code reliability and stability. The video teaches viewers how to properly test their Python code using unit testing.
Full Transcript
[Music] what is going on guys welcome back in today's video we're going to talk about unit testing in python so let's get right into it all right so unit testing is one of those things that are not very popular a lot of people dislike testing they think it's useless or at least they think it's not interesting uh it is not the most fancy thing that you can do in programming but it is very important and very practical what unit testing basically is and this is what the name already says it is testing your units in your code testing the individual units in your code so you're not doing integration tests you're not doing some workflow that you're testing you're testing the individual functions and classes and so on so let's say i have a function x that does something or a function i don't know multiply and i want to know if that function works properly then i write some tests and usually what we do if we don't do proper testing i think most of you will know this let's start with a python file called myfunctions.py this is going to be a collection of functions that we're going to test they're just going to serve as sample functions uh what we usually do when we have i don't know my function here and we have a parameter x and this function should i don't know return x to the power of two now this is something that we don't really have to test because it's one statement it's not even a proper function i mean it is a proper function but it's not a complicated function uh what we usually do when we have something like that and we want to make sure if it works properly is we just go with print statements we say okay print my function of 10 and we want to know okay does this work and then we do it for some edge cases maybe for negative numbers maybe for zero maybe we want to know what happens if i enter a string so this is how we usually test the functions if we don't do proper unit testing we write a function then we just do some print statements to see if the result is what we actually expected now this has a lot of downsides depending on the function of course if you have a script with two functions and it's just a simple script that does one or two things you don't need to do unit testing unit testing is useful if you have a medium sized or large sized code base and you want to test the functionality of the individual functions and the good thing about unit testing is that you have tests that can either pass the test or uh fail the test and the good thing is that if you change the functions uh let's say i have a complicated function with like five or uh five is not really complicated but let's say i have like 20 statements in that function or 25 statements and a pretty complex logic and then all of a sudden i see okay i can make this function simpler by removing these three lines and by adding one line and by doing this or that but i'm not sure does this function still work in the way that i expect it to work and what i have to do then is i don't have to rewrite all the test cases i can just press a button and run all the tests that i have written before that so the good thing about unit testing is that you take the time to write a couple of good tests one time and then you just have to rerun them every time you change something in your code and in this video we're just going to use some sample functions here so we're going to start by importing math import math uh we're not going to need it right away so for the first function we're not going to need math but the first function is just going to be a sample uh function that is doing some basic multiplication so multiply with loop let's say this is the function multiply with loop and what we want to have is we want to have a parameter x and a parameter y and what we're going to do is we're just going to say return the sum off y for placeholder in range x so this is basically just uh what we're doing here is we're just running a loop x times x iterations and every time we add y to the to the final sum so this is what we're actually doing here this is also what multiplication basically is what are we doing we're adding y x times so y times x this is not really complicated now how do i know that this function works now again i want to mention here those one-liners or five liners are not really complicated functions we don't really need to test them with unit tests but this is just an example but let's say i want to test this function for all the possible cases if i want to do that i would have to know okay first of all what happens if i say multiply with loop 10 and 17 so basic positive numbers what happens if i say 0 and 17 what happens if i say um for example 17 and 0. does it matter if i switch the parameters here or if i swap the parameters here what happens if i introduce negative values and so on and i don't want to do that just down below with some print statements i want to have actual tests and for this we're going to create a new python file and we're going to call it my tests dot py and here we're going to import first of all my functions because we want to use the functions um for testing or we want to test the functions and then we're also going to import unit test and this is a core python module we don't need to install anything so it is part of python already and with the unit test we can go ahead and create some test cases that we can just run and they're going to say okay we passed the test or we failed test so how do we do that we're going to say class test multiply for example this is a class and this class is going to extend it's going to inherit from unit test dot test case so this class is a test case and as you can see already pycharm tells me that i can run this this is not necessarily the case for all editors so maybe you're going to have to run this manually in the command line i'm going to uh to show you in a second how this is done but inside of that class we can now have some methods that are going to be tests so the important thing for those tests is that they always need to start with the keyword test so if i want to test this method i'm going to say test underscore and now uh for example with two positives and it is a good practice to name your functions based on what they're doing so you don't want to just say test one test two test three you wanna call them test with two positives or test with one zero or test with string expect type error or something like that so you wanna already name the function in a way that tells the developer what this test is actually testing for so in this case we're going to just test with two positives and in order to test we're going to use a function of the test case and this function is going to be assert equal so we're going to say self dot assert equal and what this function does is it takes as a parameter first a function call and second the result so the first thing is the function call which in our case is going to be my functions dot multiply with loop and here we're going to uh say for example 17 and 19 as two positive integers that we're going to multiply and then we're going to expect as a result 17 times 19. so this is the actual multiplication this is what we expect from our function no matter how it works if it wants to qualify as a multiplication we need to make sure that this is the result uh and of course we can also introduce a bunch of other tests so for example let's say we want to know okay what happens if the numbers are a bit larger so let's say i have a number like that and a number like that does it still work now of course we need to copy those here and remove the comma because the result is going to be the multiplication of those two numbers so does it work with large numbers and the important thing when it comes to unit testing is you don't want to necessarily have a lot of tests you want to have intelligent tests because if 17 times 19 works probably 18 times 35 is also going to work so it's more reasonable to test the edge cases so for for example what happens with very large numbers you can even go with larger numbers or what happens if i go with very small numbers for example one times two i want one times two of course to be two does this work or doesn't it work uh but testing with two positives is not necessarily the most critical thing here let's go ahead and try uh test with one zero and we can write a bunch of tests here so self assert equal or actually we can just copy that here and here we can see 17 times 0 should equal to 0 and of course since we have written the function as a loop we also need to make sure that it works the other way around because the x is for the range and the y is the thing that we sum up so what happens if if we swap do i still have zero as a result um and then of course the critical thing is what happens with negative numbers but before that let's test with two zeros we're just going to have one function call here zero times zero should be zero and now we can go ahead and do the same thing with negative numbers so test test with one negative and the basic the basic way of doing this is always the same you have this function call and you expect it to return this so in this case we're just going to copy that and for example we want 17 times negative 19 or negative 19 times 17 to be the same as 17 times times negative 19 and negative 19 times 17. all right so then last but not least we have two negatives what happens if we have two negatives does this work or doesn't it work so test with two negatives and here we're going to say self dot assert equal my functions multiply with loop and we're just going to say okay negative 17 and negative 19 should be the same as 17 times 19 because the two negative symbols cancel out so that should be the result and um we can now just go ahead and run those tests and we're going to see if they work or if they don't work so we're just going to click on that button here in pycharm run unit tests for my test and when we run this we're going to see okay here we have two problems we have two exclamation marks here test with one negative and test with two negative failed all the other uh all the other things went fine so we can go to test passed here uh we can see zero worked positives worked and two zeros worked but negatives did not work so you can see we got different results so this function doesn't work exactly the way that we expected it to work so we can just go ahead and call it imperfect so we saw that it doesn't work the way we wanted it to work and of course yes we could have seen that right away um so we're not learning about how to implement multi multiplication here because it was obvious that this function is not going to work for negative values but we saw that it doesn't work with a test so what we're going to do now is we're going to have a better function so we're going to call this multiply with loop we're not going to call it perfect we're going to call it better x and y as parameters and now we're going to say okay if um x is larger or equal to zero or y is larger or equal to zero uh not and sorry not or sorry and so if both are positive or both are negative then we're just going to return what we had up here uh but with a slight difference so we're going to return some but we're going to use the absolute values here because when we have negative values of course we have a problem uh but the reason we can do it like that is if we have two negatives it's the same as multiplying two positives so the absolute value is everything that we are interested in um otherwise let's say we have the case that x is less than zero but y is not less than zero then we basically just have to say return the sum of x for placeholder in range y and since y is not less than zero we're going to get a valid result and otherwise if y is less than 0 but x is not less than 0 we can do the same thing but with y here and with x here there you go so this should be a better multiplication function but we don't know right so we can assume that this is right we can also say okay i am pretty sure it's right but we would have to go through all the test cases to make sure that we don't forget anything so what we're going to do here is we're going to copy all of this here and we're going to make a second test class here we're going to call it class test multiply better it's going to be a child of unit test dot test and we're going to have the same functions here but we're going to replace multiply with loop uh by multiply with loop better so we're going to just say multiply with loop is going to be replaced by multiply with loop better there you go uh what's the problem here cannot find reference in my functions why can't you find that do we have a problem here cannot find multiply with loop why is that oh because we yeah okay i changed name to imperfect and to better so here of course we would have to do the same thing with imperfect so let's just repeat that command and change this to imperfect and test multiply imperfect there you go so i think this should work even though it's underlining everything no why does it work because it has no attribute multiply with loop better why doesn't it have that it should have that so let me fix the mistake and i'm going to go back to you in a second all right guys i found a mistake uh it's just a typo because i wrote multiply instead of multiply so we're just going to copy all of this or not copy we're going to change all this we're going to see from multiply to multiply and then it works there you go so now we're going to run all the test cases for the better version of the multiplication with loops and you can see all the tests are passed uh by the way i hope i'm not blocking everything here uh if i am blocking it i'm blocking it for quite some time already so it doesn't really matter but there you go so you can see all the tests are passed so at least that what we thought about so for example we didn't check for invalid types so we didn't check for type arrows and so on uh but for all the things we have checked for example two negatives one negative two zeros and so on uh this function works fine so let's go ahead and try another example let's say for example um we have something like a function that is called length of integer and we want to give this function integer n and what we want to know is how long is this integer and we can use a logarithmic calculation for that you can google the explanation i'm not going to explain it now but it's basically just int math.floor of math.log base 10. of n plus 1 and this gives you the amount of digits so we can go ahead and try to to see that this works so if i go print length of integer without the zero like that or one two three four five or something and now i run this you will be able to see that it actually produces the right results so let's go ahead and test this because i'm sure it won't work for all the edge cases that we can think of so let's go ahead and write some tests for this one uh so first of all let's go down here and say class test integer length or whatever you want to call it it's going to be unit test.test case by the way just one thing i want to mention before i forget it if you want to do this via the command line you cannot just run this you have to go to the directory for example in this case desktop programming python neural nine there you go um and of course i have to remove this and if you want to run the tests you cannot just go ahead and say python and then my tests because then we're going to see nothing we have to run this with python minus m and then unit test my test py so you can see here failed and run test run test ran 10 tests in 0.5 seconds we had two failures and so on so we can do this in the command line as well i just wanted to show you that and now let's go and test this length function so we're going to say class test length or what did we call a test integer length is going to be a unit test test case and the function is going to be def and we're going to start with a very basic test with positive integers or with a positive a positive integer so def test with positive integer and we're going to see what happens so uh let's say self dot assert equal and we want to say my function length of integer and we're going to pass one two three four five six for example and we wanna know that this is actually going to be six as a result here uh and we're going to do the same thing for maybe one we wanna know that one is one and we wanna know that i don't know ten is also two not also two but ten is two uh because it's right on the edge right because nine is one and ten is the first two so we wanna make sure that that works um and then we we're gonna also test with negative integers so we wanna know that it also works with negative integers so test with negative integer um and here we of course need to define what we actually want we want to know okay if i have negative one two three are those three digits or three positions or are those four positions because of course the string negative one two three has a length of 4 but the actual digits are 3. so you need to define what we actually want from the function in my case i want the negative symbol to be counted as a an additional position so i want the length of negative one two three to be four and not three so let's say self assert equal my functions dot length of integer negative one two three should be four and negative one should be two and negative one two three four five six should be seven there you go and now we also wanna test this with a zero so what happens with the zero that's def test with 0 self assert equal my functions dot length of integer 0 has to be one because zero is one digit and last but not least the only thing that we need to take care of is what happens if i um don't enter in an integer but i enter a float or a uh i don't know a boolean or a string what do we expect this function to do do we expect it to return anything or do we expect it to raise a type error now in my case i want to expect it to raise a type error so we're going to use a new function first of all we're going to create a function called test with other or invalid type and we're going to say self dot assert raises assert raises and here we pass uh first of all the exception that we expect so in this case type error i expect a type error when do i expect a type error when the function my functions dot length of integer is called we're not calling the function we're just referring to it and the parameter is for example a string of a number this should be a type error or just a string hello or a boolean true for example or even if it's a floating point number so something like that for example uh or also of course if it is a list so let's see if our function does all of this if we run that we can see okay one test is passed uh the test with the positive integers which is the most basic one all the other tests failed so we need to take care of that let's go ahead and make this function better we're going to start right away with the statement if type of n is not int race type error invalid type so we have this case handled and otherwise we're going to use this one here to just increase by two instead of just by one if we have a negative symbol so we're going to say add equals one if n is larger or equal to zero so the basic one that we already have here and else it's going to be 2 and we're going to replace this with at now the only thing that we need to also make sure is that if we have a 0 this does not crash so because the 0 is actually undefined log 10 of 0 is undefined so int math floor logarithm 10 first of all we want to have the absolute value because negative values are also undefined here um and then we also want to make sure that this is only the result that we get if n is not equal to zero otherwise we get one so we handle the zero case explicitly here so now i would assume as a programmer that all the problems are handled but i don't know so instead of just trying again with all the individual statements i'm just going to click this one button here and i'm going to see if everything is handled as you can see all the tests are passed and this is what is the good thing about testing in this case it is very trivial you would not need unit tests for those functions here it is not useful to write unit tests for such a basic collection of three functions here but if you have a project where you have different classes and different functions that work together so you have one function making use of another function and you have complicated functions and you change one thing somewhere in the code you don't know if everything is still working the way it worked before so all you need to do in order to make sure that it still does the way uh does work in the way it worked before is you just have to click one button you have to run all the unit tests and everything's fine so you write them once and you reuse them all the time because these statements are not going to change right you still want the length of this integer to be that of course if you redefine it you can change it but the test cases are just the test cases they don't care about the implementation they care about input and output they care about the result and the validity of the result so you just write them once and you rerun them all the time which is a very important thing to do especially in large projects all right so that's it for today's video hope you enjoyed i hope you learned something if so let me know by hitting the like button and leaving a comment in the comment section down below and of course don't forget to subscribe to this channel and hit the notification bell to not miss a single future video for free other than that thank you very much for watching see you next video and bye [Music]
Original Description
In this video we learn how to properly test our code in Python, using unit testing.
◾◾◾◾◾◾◾◾◾◾◾◾◾◾◾◾◾
📚 Programming Books & Merch 📚
🐍 The Python Bible Book: https://www.neuralnine.com/books/
💻 The Algorithm Bible Book: https://www.neuralnine.com/books/
👕 Programming Merch: https://www.neuralnine.com/shop
🌐 Social Media & Contact 🌐
📱 Website: https://www.neuralnine.com/
📷 Instagram: https://www.instagram.com/neuralnine
🐦 Twitter: https://twitter.com/neuralnine
🤵 LinkedIn: https://www.linkedin.com/company/neuralnine/
📁 GitHub: https://github.com/NeuralNine
🎙 Discord: https://discord.gg/JU4xr8U3dm
🎵 Outro Music From: https://www.bensound.com/
Watch on YouTube ↗
(saves to browser)
Sign in to unlock AI tutor explanation · ⚡30
Playlist
Uploads from NeuralNine · NeuralNine · 0 of 60
← Previous
Next →
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Visualizing Stock Data With Candlestick Charts in Python
NeuralNine
Python Beginner Tutorial #1 - Installation and First Program
NeuralNine
Python Beginner Tutorial #2 - Variables and Data Types
NeuralNine
Python Beginner Tutorial #3 - Operators and User Input
NeuralNine
Python Beginner Tutorial #4 - If Statements and Conditions
NeuralNine
Python Beginner Tutorial #5 - Loops
NeuralNine
Python Beginner Tutorial #6 - Sequences and Collections
NeuralNine
Python Beginner Tutorial #7 - Functions
NeuralNine
Python Beginner Tutorial #8 - Exception Handling
NeuralNine
Python Beginner Tutorial #9 - File Operations
NeuralNine
Python Beginner Tutorial #10 - String Functions
NeuralNine
Python Intermediate Tutorial #1 - Classes and Objects
NeuralNine
Python Intermediate Tutorial #2 - Inheritance
NeuralNine
Python Intermediate Tutorial #3 - Multithreading
NeuralNine
Python Intermediate Tutorial #4 - Synchronizing Threads
NeuralNine
Python Intermediate Tutorial #5 - Events and Daemon Threads
NeuralNine
Python Intermediate Tutorial #6 - Queues
NeuralNine
Python Intermediate Tutorial #7 - Sockets and Network Programming
NeuralNine
Python Intermediate Tutorial #8 - Database Programming
NeuralNine
Python Intermediate Tutorial #9 - Recursion
NeuralNine
Python Intermediate Tutorial #10 - XML Processing
NeuralNine
Python Intermediate Tutorial #11 - Logging
NeuralNine
Python Data Science Tutorial #1 - Anaconda and PyCharm Setup
NeuralNine
Python Data Science Tutorial #2 - NumPy Arrays
NeuralNine
Python Data Science Tutorial #3 - Numpy Functions
NeuralNine
Python Data Science Tutorial #4 - Plotting Functions With Matplotlib
NeuralNine
Python Data Science Tutorial #5 - Subplots and Multiple Windows
NeuralNine
Python Data Science Tutorial #6 - Matplotlib Styling
NeuralNine
Python Data Science Tutorial #7 - Bar Charts with Matplotlib
NeuralNine
Python Data Science Tutorial #8 - Pie Charts with Matplotlib
NeuralNine
Python Data Science Tutorial #9 - Plotting Histograms with Matplotlib
NeuralNine
Python Data Science Tutorial #10 - Scatter Plots with Matplotlib
NeuralNine
Python Data Science Tutorial #11 - 3D Plotting with Matplotlib
NeuralNine
Python Data Science Tutorial #12 - Pandas Series
NeuralNine
Python Data Science Tutorial #13 - Pandas Data Frames
NeuralNine
Python Data Science Tutorial #14 - Pandas Statistics
NeuralNine
Python Data Science Tutorial #15 - Pandas Sorting and Functions
NeuralNine
Python Data Science Tutorial #16 - Pandas Merging Data Frames
NeuralNine
Python Data Science Tutorial #17 - Pandas Queries
NeuralNine
Python Machine Learning Tutorial #1 - What is Machine Learning?
NeuralNine
Python Machine Learning Tutorial #2 - Linear Regression
NeuralNine
Python Machine Learning Tutorial #3 - K-Nearest Neighbors Classification
NeuralNine
Python Machine Learning #4 - Support Vector Machines
NeuralNine
Python Machine Learning Tutorial #5 - Decision Trees and Random Forest Classification
NeuralNine
Python Machine Learning Tutorial #6 - K-Means Clustering
NeuralNine
Python Machine Learning Tutorial #7 - Neural Networks
NeuralNine
Python Machine Learning Tutorial #8 - Handwritten Digit Recognition with Tensorflow
NeuralNine
Generating Poetic Texts with Recurrent Neural Networks in Python
NeuralNine
Stock Portfolio Visualization with Matplotlib in Python
NeuralNine
Analyzing Coronavirus with Python (COVID-19)
NeuralNine
Making Text Images Readable Again with Python and OpenCV
NeuralNine
Neural Networks Simply Explained (Theory)
NeuralNine
Motion Filtering with OpenCV in Python
NeuralNine
Top 5 Programming Languages To Learn in 2020
NeuralNine
Simple TCP Chat Room in Python
NeuralNine
Image Classification with Neural Networks in Python
NeuralNine
Edge Detection with OpenCV in Python
NeuralNine
S&P 500 Web Scraping with Python
NeuralNine
Simple Sentiment Text Analysis in Python
NeuralNine
Introduction - Algorithms & Data Structures #1
NeuralNine
More on: AI Pair Programming
View skill →Related Reads
📰
📰
📰
📰
AI CLI Tools Are Eating Each Other's Lunch
Dev.to · Tracepilot
Loop Engineering: The Skill That Just Made Your AI Workflow Obsolete
Medium · Machine Learning
We built a real-time Pokémon TCG AR overlay for live streams and open-sourced everything
Medium · Deep Learning
I tested the new Claude Desktop on Linux - here's how it compares to rival apps
ZDNet
🎓
Tutor Explanation
DeepCamp AI