Testing In Android — A Beginner’s Guide
In this article, We will deep dive into What is Test Driven Development(TDD), Why we should need it. How we could get started with Test Driven Development
What is Test-Driven Development(TDD)?
Test-Driven Development starts with designing and developing tests for every small functionality of an application. We write test cases for each functionality that are created and tested first and if the test fails then the new code is written to pass the test and make code simple and bug-free.
You are not allowed to write any production code unless it is to make a failing unit test pass. ~Robert C Martin
In Test-driven development we have to write the test cases for the code before writing the actual code, It sounds weird if you are writing test cases for the very first time but don’t worry we will explore it with a real-time example and we will go through step by step.
In conventional software development, we just have to refine the requirement and start developing it, once we are done with the success scenario, we think we are done with the software feature, we pass it on to the Quality Assurance Team and boom we have a big sheet of bugs, That’s the frustrating thing for every developer, Let’s check what we do wrong? Firstly we will start debugging our code, check the scenarios in which we are facing that issues, fix that issues and pass it on to the QA team again and still, we are not sure about the build should pass or not. The point is What’s actually wrong with the current software development approach? The answer is, We just go with the success scenario, We don’t go for the alternative scenarios which could happen.
Test-Driven Development forces to go for the test cases before actually write the production code. But How? We will explore it with examples in this article. We have to test the success scenario & alternative scenarios as much as the most happening alternative scenarios should cover. We could do this manually but writing the automated tests gives satisfaction and removes the fear of legacy code. Let’s explore in detail why we actually need to start test driven development.
Why do we need to get started with Test Driven Development (TDD)?
Most of the developers find it boring, time-wasting to write test cases for your success and alternative scenarios before actually write the production code, It does not make sense to cross-check your own implementation of code before releasing the build for testing as we have a testing team for this purpose, But in actual it forces you for good software development approach. Let’s explore it.
(I) Architect your code properly: It will force you to write the clean code and follow specific architectural patterns like MVC, MVI, MVP or MVVM. We shall have to follow the best coding practices and SOLID principle in our production code to actually write the good test cases for our software, If we don’t structure our code correctly, We shall not be able to test our code. It’s also a litmus paper for our quality of code.
(II) Remove legacy code: In case you just known about the testing in android and you want to implement it in your existing project It helps you to find out and remove the legacy code and dead code from your project.
(III) Keeps bugs away: When you start writing test cases before writing the production code. you will write a success scenario and then all the alternative scenarios, you will test your production code against the test cases, Which will eventually help you to find bugs in your production code.
(IV) Lessen the use of debugger: Once we start following the TDD, It will force us to think differently, implicitly makes our code cleaner in the process and we know about how our code may react in different scenarios. It will give you more confidence in the code and eventually you lessen the use of a debugger.
although there are a lot of other benefits of using TDD too, But for the sake of simplicity, I just mention some of them.
Types Of Testing
Testing is divided into three types and we denoted it as the pyramid of testing, So we can specify the priority.
This testing pyramid is a concept originally explained by Mike Cohn in his book Succeeding with Agile. The testing pyramid gives you a way to group different types of tests and gives an understanding of how many tests you should consider on each layer.
You should have lots of small unit tests, some integration and fewer UI tests.
Let’s go through each of the layers.
Unit Testing
The first question that comes up to mind when we discuss unit testing is: What is a unit? A unit is a discrete module of code it could be a class, a method or any block of code.
So we can say about unit testing:
A unit test generally tests the functionality of the smallest possible unit of code in isolation which could be a method, class, or component.
Unit tests are the basic block of testing as mentioned above in the above image. Unit tests are independent of the Android framework. What does it actually mean? It means we don’t need an actual device or an actual android environment to run the unit test. Unit tests basically run on the JVM(Java Virtual machine). Unit tests are small in size as compare to the integration and UI tests That’s why these tests known as small tests, also these tests are the fastest to run among all other kinds of tests.
Integration Testing
When we talk about the integration Tests, The first thing we have to understand: What is meant by the integration(concerning android)? Integration is basically, How things work together. So we can say the integration test is:
Testing the collaboration of multiple units
For example, We work with the database, file systems, Rest APIs, android OS components or external libraries, We have to do integration tests. These tests are actually run on the real device or the emulator and it takes more time than unit tests as it includes the framework-specific dependencies, That’s why these tests are known as Medium tests.
Following are the real-time examples for the integration tests:
(I) Insert data into the database, Now we have to check either the data has been entered into the database or not? how could we make sure? We could write the integration test for this.
(II) We want to check if the data transferred from one activity/fragment to another activity/fragment, we could test it via integration test.
(III) Check internet connectivity, So we can fetch data from the server, We could test the status of connectivity via integration test.
we should cover all these examples of integration testing in detail in upcoming articles.
User Interface(UI) Testing
User interface is the direct interaction of the user with the app. In UI testing we have to automate the interaction of users with the app. In manual testing Quality Assurance team do the same thing, Write test cases, Apply test cases one by one via interacting with the actual application, find the UI related bugs or basic app flow issues and report back to the Development Team, In Automation, we can save all this headache and time by writing the test cases and implement on our own. These tests run on an actual device or emulator, It takes more time than both unit tests and integration tests that’s why these tests called large tests.
Some real-time examples of UI testing are:
(I) check if clicks on the next button move to the next screen
(II) Check after the input data field has been filled the keyboard has been hidden.
(III) check once the login was unsuccessful, the error message shown on the screen.
These are some examples of UI tests, we will explore in detail in upcoming articles
We are just done with the conceptual part of the TDD, Now let’s start with some actual implementation.
Let’s Start With The Implementation
In this practical example, we will go with the testing of the TimeUtils file, We will create a method with the test cases. The purpose of the method in the TimeUtils file is to convert the standard time format to a human-readable format.
Let’s start happy coding ❤ ❤
Step1:
First of all, we have to add the gradle dependencies in our build.gradle
Step 2
Create a file named as TimeUtils under app/java/yourpackagename per shown in the image
we will create a extension function named as toReadableDateFormat()
Step 3:
We have two packages here, one for the unit tests mentioned as (test) and the other one is for UI & instrumental tests named as (androidTest)
As we are implementing the isolated file which is not dependent on any android framework-specific component, So, it’s obvious we will go for the Unit Test.
Step 4:
open your TimeUtils File Right-click on your TimeUtils file -> clicks on Generate-> you will get an option of Tests. Click on it a popup will be shown like this
Make sure you have selected the Junit4 for the Testing Library. Once you click on ok a new popup will appear to click on the
…\app\src\test\java/com/yourPackageHere
Step 5:
Let’s start with test cases, we have a standard time input as:
2021–06–11T18:00:00 and our output string should be like
11 Jun 2021 | 11:00 PM
First Test Case: First of all we shall have a success scenario case that gets the string input with the correct date format and return the actual readable string.
Second Test Case: Check if we pass the wrong date format string, the method should return an error message.
Third Test Case: Check if we pass an empty string, the method should return the error message.
All done!! Let's run our code.
Boom…. All the test cases have been failed. Because till now we didn’t write any production code, Now we have test cases in our mind, we have to write code according to that success & alternative scenarios and this is the actual flow of TDD, If we want to get started with TDD we have to think like a test-driven developer.
Step 6:
Let’s write the actual code while keeping in mind the test cases, First, go with the success scenario and write some production code
Let’s run again all the test cases by clicking on the red error button icon
Great!! our first test case passed, So we are done with our success scenario, Let’s do production code for the rest of the alternative scenarios too. But first, we need to check the error message we got for alternative cases:
Step 7:
We are getting an exception of parsing to let’s resolve this issue in our production code.
Our production code after resolving the issues will be like this:
Let’s run the code again:
Great!! We can check the 3 green ticks, So we are sure about 1 success scenario and 2 alternative scenarios. So now we are confident about these scenarios also the code is more readable and clean.
Step 8:
We are almost done with our first unit test, But you can see there is still one alternative scenario that is missing, We have to refactor code and that is handling null value.
Let suppose we are getting this date string from the server and the server sent the null value for the date string field. We can handle this case and return the proper error message.
Now, we are much handy and understand the actual flow of TDD so switch to the production code and handle the null condition for our date string.
Our production code will be:
Final Code
TimeUtils.kt
Constants.kt
TimeUtilsTest.kt
Conclusion
Test-Driven Development is a software development process, So if you want to start TDD you have to follow the process and once you start doing it, you will eventually love it ❤. The purpose of the article is to provide a detailed understanding of Test Driven Development, You cannot just copy/paste code from anywhere for writing tests as TDD forces you to think differently and implicitly makes your code cleaner in the process. You have to follow the process of thinking about your use-case-> Write possible test cases -> write actual production code->test your production code against your test cases>refactor your code if any edge case missing-> rerun your edge-case(alternative scenario) test case: Boom you are done with your clean, production-ready code.
Final Note
you can download and test code from here:
https://github.com/arslan555/TestingInAndroid
Happy Coding ❤ ❤
Show your love by sharing this blog with your fellow developers.
Follow me for more content about Android and Test-Driven Development and If you have any questions, email me at mirzaarslan450@gmail.com