{"id":57663,"date":"2023-06-26T15:13:52","date_gmt":"2023-06-26T09:43:52","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=57663"},"modified":"2023-09-06T15:47:33","modified_gmt":"2023-09-06T10:17:33","slug":"testing-and-code-coverage-in-android","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/testing-and-code-coverage-in-android\/","title":{"rendered":"Testing and code coverage in android"},"content":{"rendered":"<p>Android unit testing is an essential part of the software development process for Android applications. It is a way of verifying that individual units or components of the code are working as expected, in isolation from other parts of the application. In this blog, we will explore the basics of Android unit testing, including its benefits, best practices, and some popular testing frameworks.<\/p>\n<h2>Benefits of Android Unit Testing<\/h2>\n<ol>\n<li>Improved code quality: Unit tests help to catch bugs early in the development cycle, making it easier to fix them before they become more complex and harder to solve.<\/li>\n<li>Faster development: Unit tests can reduce the time it takes to develop features by helping to identify and isolate issues early, reducing the need for manual testing and debugging.<\/li>\n<li>Reduced risk: By catching bugs early and ensuring that each unit of code is working correctly, the overall stability of the application is improved, reducing the risk of crashes and other errors.<\/li>\n<li>Better collaboration: Unit tests help to create a shared understanding of the code between developers, making it easier to collaborate on complex projects and reducing the likelihood of miscommunication.<\/li>\n<\/ol>\n<h2>Best Practices for Android Unit Testing<\/h2>\n<ol>\n<li>Test only one thing at a time: Each test should focus on a single unit or component of the code, to ensure that it is working as expected in isolation.<\/li>\n<li>Test both positive and negative scenarios: It&#8217;s important to test both scenarios where the code is expected to work as well as where it is expected to fail, to ensure that it is robust and resilient.<\/li>\n<li>Use mocking and stubbing: Mocking and stubbing allow developers to create fake objects and data that simulate real-world scenarios, helping to test code that depends on external dependencies.<\/li>\n<li>Keep tests simple and readable: Tests should be easy to read and understand, with clear and concise assertions that are easy to interpret.<\/li>\n<li>Use a testing framework: Testing frameworks provide a range of tools and functionality to help with unit testing, including setup and teardown methods, assertions, and test runners.<\/li>\n<\/ol>\n<h2>Popular Android Unit Testing Frameworks<\/h2>\n<ol>\n<li>JUnit: JUnit is a widely used testing framework for Java applications, and it is also supported by Android. It provides a range of tools and features for writing and running unit tests, including assertions, test fixtures, and test runners.<\/li>\n<li>Mockito: Mockito is a popular mocking framework for Java applications, and it is widely used in Android unit testing. It allows developers to create fake objects and data to simulate real-world scenarios, helping to test code that depends on external dependencies.<\/li>\n<li>Espresso: Espresso is a testing framework specifically designed for Android UI testing. It provides a range of tools and functionality to help with UI testing, including UI interaction testing, screenshot comparisons, and performance testing.<\/li>\n<li>Robolectric: Robolectric is a popular testing framework for Android applications, which allows developers to run tests on a simulated Android device. This can help to speed up the testing process and reduce the need for manual testing on physical devices.<\/li>\n<\/ol>\n<h2>Examples<\/h2>\n<ol>\n<li>\n<h4><strong>Testing a simple calculation function<\/strong><\/h4>\n<\/li>\n<\/ol>\n<blockquote>\n<pre><code class=\"!whitespace-pre hljs language-csharp\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">CalculationTest<\/span> {\r\n    @Test\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">testAddition<\/span>()<\/span> {\r\n        <span class=\"hljs-built_in\">int<\/span> result = Calculation.addition(<span class=\"hljs-number\">2<\/span>, <span class=\"hljs-number\">3<\/span>);\r\n        assertEquals(<span class=\"hljs-number\">5<\/span>, result);\r\n    }\r\n}<\/code><\/pre>\n<\/blockquote>\n<p>In this example, we are testing a simple addition function <code>addition()<\/code> in a class called <code>Calculation<\/code>. We create a unit test case that calls this function with two arguments, and then we use the <code>assertEquals()<\/code> method to check if the result is equal to the expected value (5).<\/p>\n<ul>\n<li>\n<h4>Testing a function that throws an exception<\/h4>\n<\/li>\n<\/ul>\n<blockquote>\n<pre><code class=\"!whitespace-pre hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title class_\">ExceptionTest<\/span> {\r\n    <span class=\"hljs-meta\">@Test(expected = IllegalArgumentException.class)<\/span>\r\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title function_\">testException<\/span><span class=\"hljs-params\">()<\/span> {\r\n        <span class=\"hljs-type\">User<\/span> <span class=\"hljs-variable\">user<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-title class_\">User<\/span>(<span class=\"hljs-literal\">null<\/span>, <span class=\"hljs-string\">\"password\"<\/span>);\r\n    }\r\n}<\/code><\/pre>\n<\/blockquote>\n<p>In this example, we are testing a function that throws an exception if an argument is null. We use the <code>@Test(expected = ...)<\/code> annotation to specify that we expect an <code>IllegalArgumentException<\/code> to be thrown when we create a new <code>User<\/code> object with a null username. If the exception is not thrown, the test case will fail.<\/p>\n<ul>\n<li>\n<h4>Testing a function that depends on external data<\/h4>\n<\/li>\n<\/ul>\n<blockquote>\n<pre><code class=\"!whitespace-pre hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title class_\">DatabaseTest<\/span> {\r\n    <span class=\"hljs-keyword\">private<\/span> DatabaseHelper dbHelper;\r\n\r\n    <span class=\"hljs-meta\">@Before<\/span>\r\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title function_\">setUp<\/span><span class=\"hljs-params\">()<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception {\r\n        <span class=\"hljs-type\">Context<\/span> <span class=\"hljs-variable\">context<\/span> <span class=\"hljs-operator\">=<\/span> ApplicationProvider.getApplicationContext();\r\n        dbHelper = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-title class_\">DatabaseHelper<\/span>(context);\r\n    }\r\n\r\n    <span class=\"hljs-meta\">@Test<\/span>\r\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title function_\">testGetUser<\/span><span class=\"hljs-params\">()<\/span> {\r\n        <span class=\"hljs-type\">User<\/span> <span class=\"hljs-variable\">user<\/span> <span class=\"hljs-operator\">=<\/span> dbHelper.getUser(<span class=\"hljs-number\">1<\/span>);\r\n        assertNotNull(user);\r\n        assertEquals(<span class=\"hljs-string\">\"John Doe\"<\/span>, user.getName());\r\n    }\r\n}<\/code><\/pre>\n<\/blockquote>\n<p>In this example, we are testing a function that throws an exception if an argument is null. We use the <code>@Test(expected = ...)<\/code> annotation to specify that we expect an <code>IllegalArgumentException<\/code> to be thrown when we create a new <code>User<\/code> object with a null username. If the exception is not thrown, the test case will fail Testing a function that depends on external data<\/p>\n<ul>\n<li>\n<h4>\u00a0Testing a ViewModel with a mocked Repository<\/h4>\n<\/li>\n<\/ul>\n<blockquote>\n<pre><code class=\"!whitespace-pre hljs language-scss\"><span class=\"hljs-keyword\">@RunWith<\/span>(MockitoJUnitRunner.class)\r\npublic class MyViewModelTest {\r\n\r\n    <span class=\"hljs-keyword\">@Mock<\/span>\r\n    private MyRepository myRepository;\r\n\r\n    private MyViewModel myViewModel;\r\n\r\n    <span class=\"hljs-keyword\">@Before<\/span>\r\n    public void setUp() {\r\n        myViewModel = new <span class=\"hljs-built_in\">MyViewModel<\/span>(myRepository);\r\n    }\r\n\r\n    <span class=\"hljs-keyword\">@Test<\/span>\r\n    public void testGetItems() {\r\n        List&lt;MyItem&gt; items = Arrays<span class=\"hljs-selector-class\">.asList<\/span>(\r\n                new MyItem(<span class=\"hljs-number\">1<\/span>, \"Item <span class=\"hljs-number\">1<\/span>\"),\r\n                new <span class=\"hljs-built_in\">MyItem<\/span>(<span class=\"hljs-number\">2<\/span>, \"Item <span class=\"hljs-number\">2<\/span>\")\r\n        );\r\n\r\n        <span class=\"hljs-built_in\">when<\/span>(myRepository.getItems())<span class=\"hljs-selector-class\">.thenReturn<\/span>(items);\r\n\r\n        LiveData&lt;List&lt;MyItem&gt;&gt; liveData = myViewModel<span class=\"hljs-selector-class\">.getItems<\/span>();\r\n        List&lt;MyItem&gt; result = liveData<span class=\"hljs-selector-class\">.getValue<\/span>();\r\n\r\n        <span class=\"hljs-built_in\">assertEquals<\/span>(items.size(), result<span class=\"hljs-selector-class\">.size<\/span>());\r\n        <span class=\"hljs-built_in\">assertEquals<\/span>(items.get(<span class=\"hljs-number\">0<\/span>)<span class=\"hljs-selector-class\">.getName<\/span>(), result<span class=\"hljs-selector-class\">.get<\/span>(<span class=\"hljs-number\">0<\/span>)<span class=\"hljs-selector-class\">.getName<\/span>());\r\n        <span class=\"hljs-built_in\">assertEquals<\/span>(items.get(<span class=\"hljs-number\">1<\/span>)<span class=\"hljs-selector-class\">.getName<\/span>(), result<span class=\"hljs-selector-class\">.get<\/span>(<span class=\"hljs-number\">1<\/span>)<span class=\"hljs-selector-class\">.getName<\/span>());\r\n    }\r\n}<\/code><\/pre>\n<\/blockquote>\n<p>In this example, we are testing a ViewModel MyViewModel that depends on a Repository MyRepository. We use the Mockito library to mock the Repository and set it up in the setUp() method. Then, we use the when() method to define the behavior of the Repository&#8217;s getItems() method and return a list of test items. Finally, we call the ViewModel&#8217;s getItems() method and use assertions to verify that the returned list of items matches the expected values.<\/p>\n<ul>\n<li>\n<h4>Testing a LiveData transformation function<\/h4>\n<\/li>\n<\/ul>\n<blockquote>\n<pre><code class=\"!whitespace-pre hljs language-scss\"><span class=\"hljs-keyword\">@RunWith<\/span>(MockitoJUnitRunner.class)\r\npublic class MyViewModelTest {\r\n\r\n    <span class=\"hljs-keyword\">@Mock<\/span>\r\n    private MyRepository myRepository;\r\n\r\n    private MyViewModel myViewModel;\r\n\r\n    <span class=\"hljs-keyword\">@Before<\/span>\r\n    public void setUp() {\r\n        myViewModel = new <span class=\"hljs-built_in\">MyViewModel<\/span>(myRepository);\r\n    }\r\n\r\n    <span class=\"hljs-keyword\">@Test<\/span>\r\n    public void testGetItemNames() {\r\n        List&lt;MyItem&gt; items = Arrays<span class=\"hljs-selector-class\">.asList<\/span>(\r\n                new MyItem(<span class=\"hljs-number\">1<\/span>, \"Item <span class=\"hljs-number\">1<\/span>\"),\r\n                new <span class=\"hljs-built_in\">MyItem<\/span>(<span class=\"hljs-number\">2<\/span>, \"Item <span class=\"hljs-number\">2<\/span>\")\r\n        );\r\n\r\n        MutableLiveData&lt;List&lt;MyItem&gt;&gt; liveData = new MutableLiveData&lt;&gt;();\r\n        liveData<span class=\"hljs-selector-class\">.setValue<\/span>(items);\r\n\r\n        LiveData&lt;List&lt;String&gt;&gt; result = myViewModel<span class=\"hljs-selector-class\">.getItemNames<\/span>(liveData);\r\n        List&lt;String&gt; expected = Arrays<span class=\"hljs-selector-class\">.asList<\/span>(\"Item <span class=\"hljs-number\">1<\/span>\", \"Item <span class=\"hljs-number\">2<\/span>\");\r\n\r\n        <span class=\"hljs-built_in\">assertEquals<\/span>(expected.size(), result<span class=\"hljs-selector-class\">.getValue<\/span>()<span class=\"hljs-selector-class\">.size<\/span>());\r\n        <span class=\"hljs-built_in\">assertEquals<\/span>(expected.get(<span class=\"hljs-number\">0<\/span>), result<span class=\"hljs-selector-class\">.getValue<\/span>()<span class=\"hljs-selector-class\">.get<\/span>(<span class=\"hljs-number\">0<\/span>));\r\n        <span class=\"hljs-built_in\">assertEquals<\/span>(expected.get(<span class=\"hljs-number\">1<\/span>), result<span class=\"hljs-selector-class\">.getValue<\/span>()<span class=\"hljs-selector-class\">.get<\/span>(<span class=\"hljs-number\">1<\/span>));\r\n    }\r\n}<\/code><\/pre>\n<\/blockquote>\n<p>In this example, we are testing a transformation function in a ViewModel <code>MyViewModel<\/code> that converts a list of <code>MyItem<\/code> objects to a list of their names. We set up a test list of items, create a LiveData object with this list, and pass it to the ViewModel&#8217;s <code>getItemNames()<\/code> method. We use assertions to verify that the returned list of names matches the expected values.<\/p>\n<p>These are just a few examples of writing unit test cases in Android using the JUnit &amp; Mockito framework. Unit tests can be written for any function or component in an Android application, and they are a valuable tool for ensuring code quality and catching bugs early in the development process.<\/p>\n<h2>Code Coverage using Kover in Android<\/h2>\n<p>Code coverage in Android refers to the measurement and analysis of how much of your application&#8217;s source code is executed by your tests. It provides insights into which your tests are exercising parts of your code and identifies areas that may lack sufficient test coverage. Code coverage is a metric that helps you assess the effectiveness of your test suite and can be used to improve the quality and reliability of your Android application.<\/p>\n<p>Code coverage analysis can be performed at different levels, including:<\/p>\n<ol>\n<li><strong>Line coverage<\/strong>: Measures the percentage of individual lines of code executed by the tests.<\/li>\n<li><strong>Branch coverage<\/strong>: Measures the percentage of decision points (branches) in your code that have been taken by the tests. It determines whether both true and false branches of conditional statements have been executed.<\/li>\n<li><strong>Method coverage<\/strong>: Measures the percentage of methods or functions that the tests have called.<\/li>\n<\/ol>\n<p>To measure code coverage in Android using the Kover library, you can follow these steps:<\/p>\n<ul>\n<li>Add dependencies to your project. Include the Kover plugin and dependencies in your project&#8217;s build.gradle file:<\/li>\n<\/ul>\n<blockquote>\n<pre><code class=\"!whitespace-pre hljs language-groovy\">buildscript {\r\n    dependencies {\r\n        \/\/ Other dependencies\r\n        classpath 'com.vanniktech:gradle-android-kover:0.6.0'\r\n    }\r\n}\r\n\r\napply plugin: 'kover'\r\n<\/code><\/pre>\n<\/blockquote>\n<ul>\n<li>Configure kover in your module&#8217;s build.gradle file. Inside the module&#8217;s build.gradle file, apply the kover plugin and configure it:<\/li>\n<\/ul>\n<blockquote>\n<pre><code class=\"!whitespace-pre hljs language-groovy\">apply plugin: 'kover'<\/code><\/pre>\n<pre><code class=\"!whitespace-pre hljs language-groovy\">kover {\r\n    jacocoVersion = '0.8.7'\r\n    reportDir = \"${project.buildDir}\/kover\"\r\n    enabled = true\r\n}\r\n\r\nandroid {\r\n    \/\/ Other Android configuration\r\n    testOptions {\r\n        unitTests.all {\r\n            jacoco {\r\n                includeNoLocationClasses = true\r\n            }\r\n        }\r\n    }\r\n}<\/code><\/pre>\n<pre><code class=\"!whitespace-pre hljs language-groovy\">apply plugin: 'kover'<\/code><\/pre>\n<\/blockquote>\n<ul>\n<li>Run your tests with code coverage. To run your tests with code coverage, execute the following command in the terminal. Below command runs your unit tests and generates a code coverage report.<\/li>\n<\/ul>\n<blockquote><p><code class=\"!whitespace-pre hljs language-shell\">.\/gradlew testDebugUnitTestCoverage<\/code><\/p><\/blockquote>\n<ul>\n<li>View the code coverage report. After running the tests, you can find the generated code coverage report in the specified <code>reportDir<\/code> folder (e.g., <code>${project.buildDir}\/kover<\/code>). Open the HTML report in your web browser to view the code coverage metrics.The kover library uses the JaCoCo code coverage tool under the hood, and the generated report will show information about the percentage of code coverage for each class and method in your project.\n<p><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-57662 aligncenter\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/06\/Screenshot-2023-06-20-at-11.35.44-AM.png\" alt=\"\" width=\"3342\" height=\"784\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/06\/Screenshot-2023-06-20-at-11.35.44-AM.png 3342w, \/blog\/wp-ttn-blog\/uploads\/2023\/06\/Screenshot-2023-06-20-at-11.35.44-AM-300x70.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/06\/Screenshot-2023-06-20-at-11.35.44-AM-1024x240.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/06\/Screenshot-2023-06-20-at-11.35.44-AM-768x180.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/06\/Screenshot-2023-06-20-at-11.35.44-AM-1536x360.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/06\/Screenshot-2023-06-20-at-11.35.44-AM-2048x480.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/06\/Screenshot-2023-06-20-at-11.35.44-AM-624x146.png 624w\" sizes=\"(max-width: 3342px) 100vw, 3342px\" \/><\/li>\n<\/ul>\n<p>Feed your curiosity \u2013<a href=\"https:\/\/www.tothenew.com\/blog\/\">\u00a0read more<\/a>\u00a0of our insightful blogs.<\/p>\n<div class=\"ap-custom-wrapper\"><\/div><!--ap-custom-wrapper-->","protected":false},"excerpt":{"rendered":"<p>Android unit testing is an essential part of the software development process for Android applications. It is a way of verifying that individual units or components of the code are working as expected, in isolation from other parts of the application. In this blog, we will explore the basics of Android unit testing, including its [&hellip;]<\/p>\n","protected":false},"author":1598,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":1419},"categories":[518,1816],"tags":[5264],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/57663"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1598"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=57663"}],"version-history":[{"count":3,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/57663\/revisions"}],"predecessor-version":[{"id":58348,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/57663\/revisions\/58348"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=57663"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=57663"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=57663"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}