Test-Driven Development in Python: Test First Code Later

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what is going on guys welcome back in this video today we're going to learn about test driven development what it is and how to do it in Python so let us get right into it not a GED all right so the basic idea of test driven development is that we first write our tests and then we write our actual code so in a sense we write our code to pass all the tests that we have already written we don't write tests for already existing code so it's the other way around and we're going to get right into this with an example I'm going to open up a new python file calculator. py and this is going to be our actual code so to say we're going to implement a simple calculator class but we're not going to write the code yet we're just going to define the methods so we're going to say class calculator and we're going to define the methods at which takes X and Y as parameters and we're going to just add pass here to fill the space it doesn't have any any functionality yet and we're going to do the same thing with subtract X and Y C and then def multiply X and Y pass and then we're going to say divide X and Y pass so this is our class now and we don't have any implementation yet we know okay there are four methods and we have parameters and the structure and all that and maybe we can add type pins Maybe we can say okay this should be uh only an integer or something you can make the type definitions here but all in all this is not implemented the idea of test driven development now is to go ahead and Define the tests first before writing any codes so we want to Define what should this program do how should it behave in different situations then you put that into code using uh unit tests and then you write your class you implement your class so that it passes all the tests and what we can do for this now is we can create a new python file testore uh calculator py and here we're going to import unit test and we're also going to import from calculator the calculator class so our code that we will write at some point um and here now we create a class test calculator which extends from unit test. test case so this is just ordinary testing and what we're going to do here now is we're going to have a setup method which is going to be in this case very simple so here just Define what happens before any of the tests are being run and in this case we're just going to say self calculator is going to be initialized as a calculator instance and now we can Define test cases so we can think about uh the different cases or the different ways in which we could use this calculator and the important thing is you want to use uh you want to think about positive cases and about negative cases so you don't want to just test for the functionality of adding two numbers properly you also want to test okay what happens when I enter a list what happens when I enter a string what happens when I uh you know enter nonone values or something like that you want to define a different cases and what should happen in those cases so a very simple case would be and usually you want to specify the names or you want to choose names for the individual functions here for the individual tests that describe what the test is doing and what you expect so for example testore add numbers returns sum for example that is a test name and what we would do here is we would say result equals and then we would say self calculator at and you can choose some numbers here usually what you want to do is you want to do edge cases in the case of at we don't really have edge cases in the case of division an edge case or a special case would be division by zero for example or maybe when you have some limits that you want to check you want to see okay what happens at the limit you want to use the values very close to the Limit and not just arbitrary values but what we can do here now is we can say Okay 20 and 60 for example let's choose two very simple integers what I want to make sure is that the calculator actually uh computes the proper sum so what I'm going to say is I'm going to say self. assert equal and I want to assert that 20 + 60 so the actual sum is the same as the result of this class um yeah so we get this then what we can do is also we can do the same thing for floating Point numbers so we can say what if it's 20.56034° use case of the ad function now we might think a little bit further okay what should happen if I enter different types of things and one thing that is clear is if I enter just something if I enter just some basic strings or if I enter some uh you know nonv values or something that this should fail so it should it should raise a type error this is how I want to define the functionality or the behavior of this function so test add nonn numbers r type error for example and then we can say Okay self assert raises so I want to assert that an exception is being raised and what should happen is I want to call the function so the first thing uh that I pass here actually is the exception I want to have a type error and how do I want to produce this type error so what should I check uh if it produces this type error first of all I pass a callable and the callable in this case is self calculator at important do not call the function you want to pass the callable you want to pass the function as an entity and then you want to pass the arguments separately so for example the arguments could be hello world if the arguments are hello world I'm expecting a type error then I can copy this and I can change this a little bit so I also expect a type error if one of the two values here is an integer and the other one is a string so if one of them is something that I cannot work with then I also want to erase an error so like this as well um also I want to get an error if I have a string that contains numbers but it's not really a number so for example if I have uh 20 and I add 20 to 6010 20.3 which could be an IP address this should not be treated as a number it should not be typ casted which lead me leads me to the next thing I want to be able to typ cast cast strings if they contain actual numbers so I can say here third test case test at string numbers returns sum and then what I can do is I can say okay the result of self calculator at uh what I want to do here is I want to add the two strings 50 and 60.7 now the important thing is by default what a string adding operation would do is it would just concatenate these two strings so the result would be a string that looks like this 50 60.7 we want to have the actual calculation since both of these things are actually numbers they just have to be typ casted properly so we want to assert the equality between 50 plus 60.7 this should be the same as the result of the calculation and uh we also want to be able to do this if just one of them is a string and the other one already is a number so they should have the same result and um the other way around they should also have the same result there you go um and now we have this definition of how our ad function should work let's say this is now everything that we are interested in of course in a real project you will have a more complex function you will probably write many many more tests because you want to have all the different cases the important thing about test driven development is that your tests should be very reliable you should know that when all your tests pass your program works properly your tests are sort of the definition of functionality so the tests Define does the program work or not and the goal is to find good tests so the goal is to find very uh tests that are very hard to pass and that Define the functionality of the program so so they should take care of all the bugs all the edge cases they should Define all the functionality you should know that when you run the test and you get only green checks that your program works the way you defined it to work so if I run this right now here you're going to see that I have three tests and all of them fail so probably I'm going to see this where are we going to see this usually it says failed three or something there you go failed failure none of these work now I can go ahead now and start with the implementation because now I can say okay my tests are done I can go into my code and actually write code that passes all these tests and I can start with a very primitive solution I can just return X+ Y and see what happens so this would be a very basic implementation I run the tests and now you can see okay one of the tests here passes the other two are still failing the reason for that is obviously because and you can see now failures equals 2 because uh the basic functionality here the first test succeeds I just have numbers I add them this is what I expect so this works but you can also see that the other two do not work so I can run this again and we can see exactly what the problem is here type error not raised okay and here we have that 11.7 is not equal to the string concatenation obviously so what we can do now is we can adjust a function to pass the test we can say something like if not is instance so if X is not an instance instance of an integer and not an instance of float is instance X float if it's neither an integer nor a float I can erase a type error and then I can do the same thing for y so I just say that both of them should produce a type error if they're not numbers and then I can test this again so I can run the tests again and now you can see two tests pass but the third one does not because the problem is that I'm just raising a type error now even though I should typ cast these numbers so now I have to add some functionality that takes care of the third test um and what could I do here I could do something like okay if the instance is not uh integer and not float what I want to do is I want to uh check if this is a number and how could I do that I could say if X um X being a string obviously since it's not an integer or a float uh I mean obviously it's it's actually not obvious because it could also be something else but I didn't test for that so you can see if the test is not there if I don't have a test testing if this is for example a numpy array um I don't have this case handled and because of that my test would pass but I would still have some problems here but let's now naively assume that this is a string because that is all I'm testing for I just want to pass all the tests uh if this is a string there is the function or the method is numeric so I can just say is numeric and this would check if the if the string is numeric the problem with that is that it does not take into account uh decimal points so if I have something like 10.8 as a string it will not classify this as numeric because it has a point in there so what we can do is we can first call the function replace to replace the point by an empty string but only once and this is why we have this test case here with the IP address sort of structure because if we replace all the points this would also succeed and this is not what we want we only want to remove a single point a single decimal point and then we want to see if the result after doing that is numeric if yes what we want to do is we want to uh or actually let's let's test for the negative if it is not numeric we want to raise a type error otherwise we want to just type cast so so X is going to be float of X and we can do the same thing here for y y equal float Y and this would now do the type casting so I can run this again and you can see all my tests pass now the idea again of test driven development is that if your tests are of high quality if you covered all the cases if you thought about every Edge case every scenario everything that could happen and you define it as a test when you see only green checks you're good to go in this case that is not the case so here I have the problem that I could pass all sorts of values that are not strings not numbers I could also uh for example a very simple thing that I could do is I could uh pass a negative number so I can pass - 50 as a string for example and this would already not work because I'm not handling this this is not going to be recognized as numeric by the method but it's also not not handled by me manually so what I could do here and this is also part of the back and forth of course you have test driven development but as you go and Implement your code you're going to see okay this is a case I encountered a case that I did not Define in a test this is a problem so I'm going to write an additional test test add and then I could say um let's call this string negative numbers returns sum and then I could fine I could copy all of this here and I could just add a negative to to this for example here uh so I just need to be careful here this would be like that and this would be like that and of course now this is not going to be passed so then the next step would again be to handle this in the app ad function here which I'm not going to do now for this video but that is the idea of test driven development you define a lot of tests you make sure they cover all you want to cover and then you write the code so that it passes all the tests so that's it for today's video I hope you enjoyed it and hope you learned something if so let me know by hitting a 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 much for watching see you in the next video and bye that
Info
Channel: NeuralNine
Views: 10,502
Rating: undefined out of 5
Keywords: python, testing, unit test, unit testing, unittest, python unit testting, python testing, test, test-driven development, tdd, python tdd, test driven development, python test driven development, python test-driven development, python tdd unit testing
Id: Y6Q3ZWXIvms
Channel Id: undefined
Length: 15min 43sec (943 seconds)
Published: Sat Nov 18 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.