Writing Our First Unit Tests - Testing on Android - Part 3

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hey guys welcome back to new video in this video we are finally going to start to write our first unit test and for that i just created an empty android studio project so this won't be part of any big project here just an empty android studio project in which i will teach you the basics of unit testing before we will apply those principles in a real project so first of all what i will do is i will insert one more dependency here so if you open up our build.gradle module app file then you can see by default we already have three dependents here regarding testing on the one hand we have junit which is the standard testing framework for android and for java or kotlin of course and by the way we can update the version here of that currently it's 4.12 we can press alt plus enter to change it to 4.13 i will separate those a little bit here then you can see we have an android test implementation for some extension functions of junit and we have an android test implementation for espresso espresso is a library for ui testing which we actually don't need here but it is still included in our dependencies by default but what i will paste here is a library called truth and that is a library by google which will make our assertions in our test cases much more readable for us but you will see what i mean when we write the actual test cases what's now interesting is what is the difference between test implementation and android test implementation so if we take a look at our root package then we have that java package here and then we have three com folders one for our main source code which you always used and we have two other folders here android test and just test and all those folders so each of those is called a single source set so whenever i talk about source sets in this series then i mean those folders are one of those folders and the difference now between android test and test is that we put our test cases that only run on the android emulator so our integrated unit tests if you listen carefully those tests belong in the android test directory and the other tests that don't rely on any android components such as context or something like that those test cases come into this test folder so the tests inside of this test folder one on on the jvm are not on the android emulator which makes them run much faster because we don't need to launch an emulator for that and if we now take a look at our gradle dependencies here again then you can see we have test implementation android test implementation the android test implementation will include this dependency only for our android test source set and the test implementation keyword here will include this junit library only for the test source set so that means if we would also need for example this truth library here if you would also need that in our android test implement in our inner test folder then we would simply need to copy that line and paste it and change this to android test implementation and if we now sync this then afterwards we also have that truth library available in our android test source set and of course just as usual you can also find this dependency in my github repository where you can find the link to in this video's description just as usual but let's actually jump into testing right now because i know you're waiting for that and as i explained in the last video we will follow through this series with tdd so test driven development and that means we will write the test cases before the actual function implementations and the function i want to show you or the function we want to test in this video is just as i also showed you in the last video a function that should validate registration input so we will have a function with a username a password and a confirmed password and that either returns true or false depending on if that input is valid or not and if you watched the last video carefully then you know that we of course first have to declare the function declaration because otherwise we can't call that function so what we will do here is we will go in our main search set where our main activity is and here we will create a new kotlin folder class which i will call registration util and that will be an object so singleton we don't need to create an instance of that class to use the functions in it press enter here and here we now want to specify the signature of our function we want to test so that will be a function validate registration input and it will take a username which is a string it will take a password which is also string and it will take a confirmed password which is also a string and then it will return a boolean so it will return true if that input is valid or it will return false if that input is not valid for example if the username was left empty so right now we specified the signature of that function but of course we need to return something here because otherwise we can't call that function or it won't even compile so here we can just choose anything because most of our test cases will fail anyways so let's just return true here and always take our input here as valid and now i need to think about when is such an input actually a valid input and when is it not valid and for that let's actually make a little comment here or documentation so first of all the input is not valid if the the username is empty or actually the username or password is empty then we have the possibility that the username is already taken for which i will create a list here that simulates for example a database that contains users so private well existing users which will be a list of oops list of and here we will just put in some persons peter and carl and those users already exist so if we want to register with the username that is already in that list then we would declare that as not valid then we would also have the case that the confirmed password is not equal the real password so the confirmed confirmed password is not the same as the real password and finally a rule that i thought of myself which you don't need to do but just for practice here the password contains less than two digits and everything else will basically make our input a valid input so now we need to consider those rules here and write test cases out of that and we can generate a test class by right clicking on the class we want to generate the test class of so in this case registration util right click generate or press alt plus insert and here we can select test so that's what we want to do here press enter and then we want to choose junit 4 as a testing library there is also junit 5 but for android it's not working for everything so what we will use here is junit 4. and that's fine basically we can choose a name for the class which is registration util test that is the naming convention for test classes so just the normal class name followed by test and then we can click on ok and we are prompted to choose a folder this test class should belong to so either the android test directory or the test directory little homework for you in which of these two directories should you put this test class here i will pause this video and after that you will get the answer all right so of course this test belongs in the test directory because it's not this function does not rely on any android components such as context activity or fragment we just validate some strings here so we put this in the test directory and this function can run on the jvm let's click ok here and then you can see android studio generated this registration util test class for us and inside of this class we can now define our test cases for the registration util object so let's open this class here and in here we will define functions that will use insertions to test our actual class or our actual functions so let's actually write our first unit test here because if we take a look in our registration util class you can see we can write our first unit test to check if our username is empty then the input should not be valid and that's what we are going to test in our first test case so we will declare a function here and now the naming for those test functions is very interesting because the naming that i like the most is with these backticks because inside of these bag ticks in kotlin we can put anything and that will be the function name so we can write empty username returns false and that is the name of our test case function of course you should never choose this type of naming for your real functions in your real program but in testing this is actually fine because we don't call our functions by ourselves instead j unit will do that for us but right now this is just a regular function to make this function a test case for that we need to annotate this function with add test and now you can see the name turned yellow and we also have this little play symbol here to actually run the test case or the play symbol on our class to run all test cases inside of our class here so what will we actually put inside of this function now what we will do is we will create a variable result and we are going to set that to registration util so we have access in our test class to our main source set classes because we need that of course and then we're going to call the validate registration input function and in here we're just going to provide exactly the input that this test should test so this test should test that the username is empty the password is something valid so at least two digits and the repeated password is also repeated correctly so everything is working fine just the username is is empty basically and that will cause our test to fail or that should cause our test to fail and now that we have that result which is either true or false depending on if that function that we wrote in our registration util class validated that input or not um now we can use that result to make an assertion so we can now assert that this result has a specific value and we you do that with assert that and you can see we only have two options here and that's a little bit dumb because junit also comes with that assert that function but we don't want to use the function of junit because we included our own assertion library from google the truth library and we want to use that instead so what we need to do is we need to remove that import statement from a junit here and then we can if we write the parentheses here we can import that assert that function and this time we import it from the truth library because that will make it much more readable as you will see in a sec so now inside of this assert that function we can assert that our result and after that function rewrite dot is false so that is very human readable we just assert that the result is false and if the result is true at that point the test case will fail it's actually that simple so let's actually run the test case click on that little play symbol here and click on run empty username blah blah blah and then you can see android studio will do some build stuff here and it will run our test and this test case failed because our empty username returns false that was what we expected with this test case that was the expected behavior of our validate user validate registration input function but in our registration neutral class we return true in any case so that's what this that's what caused this test case to fail but of course in our case here that is exactly what we expected to happen because we haven't implemented our validation function yet before we do that we want to write all of our other needed test cases first so let's actually we can copy that function actually and just modify it every time a little bit paste it down here we want to have a test case if the input is valid of course so valid username and correctly repeated password returns true and here we need to provide a username this time because we want a valid input let's choose fill up here and the password is valid and the confirmed password is valid as well so this time we don't want to assert that this result is false instead we want to assert that this is true and of course whatever we put inside of this assert that function so our result here depending on what we put in there it will affect what we can call on that assert that block because we put a boolean in there of course then we can only assert that this boolean is either true or false so if we would write a cert that hello so as a string and write a dot after that then you can see we have lots of more functions which we can use with that assert that function so we could assert that the string contains a specif a specific value that it does not contain a specific value that it ends with a specific string that it has a specific length that it's empty um and what's what is very important is this is equal to so we can just check if the string hello is equal to hello which would return true in this case of course so just as a quick little overview that you see that there are also other functions we can call on that assert that block depending on what the type is we put into it and then let's actually write another test case we can copy that block again paste it below this should now test that username exists the username already exists returns false of course and in here we are just going to put a value that is in our list here so either peter or carl let's choose carl here provide a valid password and a valid confirmed password in this case we want to assert that this is false and what i now want from you is that you write the remaining test cases so i think we have three missing on the one hand that is um what happens if the password is empty and then we have the case that the password was repeated incorrectly and we have a test case that the password contains less than two digits so for those three scenarios i want you to now write test cases and i will pause the video here i will paste my test cases and after that we can continue but really make sure that you do this on your own because just watching videos won't help you in any way alright so welcome back i hope you wrote your test cases so what i will do is i will paste my solution here right now on the one hand we have the test case when we incorrectly confirm the password then it should return false so we have a valid username a valid password but we confirmed it incorrectly then we assert that the result is false then we have an empty password that should return false so that username again empty password correctly confirmed password because it's the same as the initial password but since the password is empty we assert that the result is false and also if we have a password with less than two digits then we return false two so here we have a password with only a single digit in that case we assert that the result is false as well and if we now scroll up here and run all of our test cases in this class so by clicking on this little icon next to our class and run registration util test then we can see okay we have six test cases here and only a single one succeeded because we return true here in this function by default and of course the test case that checks if the result is true will always succeed but now the next step in test driven development is to write the actual function implementation so that all of our test cases succeed here and for that we need to switch back to our registration util class and implement this function here so we remove this return statement and yeah write the implementation and yes that is now a very simple example here so on the one hand if our username dot is empty or our password is empty in that case we want to return false then we also want to check if the username is already taken so if our user name is in or not is in is just in our existing users list then we want to return false as well and i know we could write that other statements as a single boolean expression and to return that i just do it like this so it's a little bit more readable for you then we want to check if the confirmed password is not the same as the real password so if password is not equal to confirm password we also want to return false and we want to check if the password contains less than two digits so if um password dot count with that lambda function and here we can check if it is equal to or not is equal to it that is digit is digit so if the character is digit we will count it and if the result of that count function is less than 2 then we want to return false and now we basically considered all of our rules that cause our input to fail so afterwards if we haven't returned so far we can return true so yeah that's it for this function let's actually go back to our little test box down here and click on this green arrow to run these test cases again let's do that wait a little moment and you can see now all of our test cases succeed which is a super satisfying feeling here and that means now for the whole development time of our application that we do here we can always check if the functionality of this function is working with only a single click and of course this function was pretty straightforward so you you might think now i could have written that before the test cases and yes that is true but the point of writing the test cases before the actual implementation is that you think more of the edge cases of a specific function because this was a simple function but you won't write simple functions all the time and if you write test cases before the actual implementation you might think more about what the function needs to consider and since writing test cases can be a little bit exhausting this is also a good habit to write the test cases before the actual implementation because then you will always do it if you say well i do these test cases i write these test cases sometime later then it's very likely that you will never do it all right guys i have a homework for you and i really suggest you to do that because if you don't apply what you learn here you won't learn anything in the end because you can't learn programming by watching a video or by reading a book in the end you have to code on your own and that's why i thought i will make some homeworks here in these videos in the series and in this video i will give you two functions and you should test if those functions are working properly so on the one hand i have a fibonacci function here if you don't know what fibonacci numbers is and how you can calculate them here is a little definition you can by the way find these this homework here in my github repository you can also find the link in the description here of this video so just pull this repository and write test cases for those functions inside of this homework class that test if this function and the other function here is working perfectly fine or not and if not then you should find the error in that function so as you can see the other function here is about checking braces so you will get a string as a parameter and that string contains parentheses here and if those parentheses or braces are set incorrectly just as here so we have two closing parentheses and one opening parenthesis um then this function will return false and if it was a string like this it should return true and you should check if this function is working properly or not and you should of course check that with test cases so please let me know below if you like the series so far if you learn something new and also if you are not a subscriber of my channel yet then quickly make sure to do that click on the subscribe button to get regular android content every second day huge benefits for you have a nice day see you next video bye bye [Music] you
Info
Channel: Philipp Lackner
Views: 41,370
Rating: 4.9659863 out of 5
Keywords: testing, android, test, test case, junit, mockito, mock, fake, stub, tdd, test driven development, intellij, android studio, unit test, unit testing, integration test, integrated test, end to end test, ui test, kotlin, mvvm, live data, coroutines, dagger, retrofit, room, database, roboelectric, android test, jvm, flaky test, development, programming, git
Id: W0ag98EDhGc
Channel Id: undefined
Length: 23min 43sec (1423 seconds)
Published: Sun Aug 16 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.