0% found this document useful (0 votes)
4 views50 pages

Unit Testing for Android

The Android Unit Testing course, presented by Yasmeen Hosny, spans 18 hours and covers essential topics such as unit testing, testing ViewModels, LiveData, and dependency injection. The course emphasizes the importance of testing in app development, outlining various testing types and strategies for writing effective tests. Participants will engage in labs and projects, with evaluations based on lab performance and a final project.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views50 pages

Unit Testing for Android

The Android Unit Testing course, presented by Yasmeen Hosny, spans 18 hours and covers essential topics such as unit testing, testing ViewModels, LiveData, and dependency injection. The course emphasizes the importance of testing in app development, outlining various testing types and strategies for writing effective tests. Participants will engage in labs and projects, with evaluations based on lab performance and a final project.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 50

Android Unit Testing

Presented By
Yasmeen Hosny
About Course
• Duration (18 hours)
- 2 Lectures (6 hours)
- 2 Labs (6 hours)

• Evaluation
40% on Labs
60% on Project
Agenda

• Introduction to Unit testing


• Testing ViewModel
• Testing livedata
• Dependency Injection
• Testing doubles
• Testing Repository
Introduction
What is testing
A test is a manual or automatic procedure used to evaluate if the System
Under Test (SUT) behaves correctly.

Testing your app is an integral part of the app development process.


By running tests against your app consistently, you can verify
1. Your app's correctness.
2. Functional behavior.
3. Usability.

During this course when mentioning anything related to writing a test we


will be referring to the automatic procedure form of a test.
Testing Goals
Everything is OK!
• Safer code refactoring, allowing you to optimize code without worrying about regressions.

• Stable development velocity, helping you minimize technical debt.

Increase Development speed


Rapid feedback on failures.

Document your code


Testing Types
Local Instrumented
Run locally on development Run on real or emulated Android
machine’s JVM and do not require devices.
an emulator or physical device. Related to UI.
Related to business logic.
Run fast Much slower
They act less like they would in the They reflect what will happen in the
real world. real world (Have more fidelity)

JUnit Espresso
Testing Scopes
Unit Testing

• Single function or class.

• Helps to point of failure.

• Run fast, usually local.

• Low fidelity
Integration Test

• Several classes or single feature.

• Ensure classes work together.

• Can be local or instrumented


End to End Test

• Large portion of the app.

• Test the app work as hole.

• Always be instrumentation test.


Testing Source Sets
When you create a new Android project, you
get the following three source sets by default.
They are:
● main: Contains your app code. (known as
build variants)
● androidTest: Contains instrumented tests.
● test: Contains local tests.
Testing Dependencies
Some Gradle dependencies need to be added, they starts with
testImplementation,androidTestImplementation used
with Junit and Espresso libraries.

//default testing dependencies


testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation
'androidx.test.espresso:espresso-core:3.4.0'
Default Testing Packages
● Test source sets knows about the main source set but the main
source doesn’t know about the Test source sets

● Both test source sets doesn’t know anything about each other

● When you upload your application to the store none of your test
cases will be added.
TO-DO Notes Application
The app allows you to:
1. Add tasks to complete and displays
them in a list.
2. Mark tasks as completed or not.
3. Filter tasks.
4. Delete tasks.

This app is written in Kotlin, has several


screens, uses Jetpack components, and
follows the architecture
Getting Started
Under the test source set you will find ExampleUnitTest class.

Let’s try to run this test.


Getting Started
After running the test. You can see the result, either left next to it or in
the run tab.

Great! Test
passed.
Make your test readable

Readable Tests Strategies

1. Naming
2. Code Structure (Given/When/Then)
3. Assertion framework
Naming
General Form:
subjectUnderTest_actionOrInput_resultState

subjectUnderTest: what we are really testing(function, class or feature)


actionsOrInputs: optional you can delete it in case of no inputs.
resultState: The result /behavior that you expect your function to return.

Ex:
getActiveAndCompleteStates_noCompleted_returnZeroCompleteHundredActive
Given – When – Then
Sometimes called as Arrange Act Assert (AAA)
It is a strategy to structure the code inside the testing function
• Given: sets up the objects and the state of the app that you need for
the test
• When: make the actual actions and changes to the subject under test
• Then: checks what happen when you do the action how your changes
affect (often done using assertion framework)
Assertion framework
We can use different assertion framework to make our tests more readable.
For example:
• Hamcrest
• Truth

testImplementation “org.hamcrest:hamcrest:2.2”
testImplementation “org.hamcrest:hamcrest-library:2.2”

assertEquals(0f, result.completedTasksPercent)
assertThat(result.completedTasksPercent, `is`(0f))
JVM
Testing
(Logic)

Writing First Test


Writing First Test
Our goal is to write tests for
getActiveAndCompleteStats()

A function which calculates the percentage of active


and complete task stats for you app.

You can see these numbers on the statistics screen of


the app.

Will it be local or instrumented test?


Writing First Test - Test cases
• If there are no completed tasks and one active task(that the percentage
of active tests is 100%,and the percentage of completed tasks is 0%.)

• If there are two completed tasks and three active tasks (the completed
percentage should be 40f and the active percentage should be 60f.)

• If there are empty list (that the percentage of active tests is 0%,and the
percentage of completed tasks is 0%.)

• If there is NULL (that the percentage of active tests is 0%,and the


percentage of completed tasks is 0%.)
Writing First Test
1. In the main source set, in todoapp.statistics, open StatisticsUtils.kt.

2. Find the getActiveAndCompletedStats function.

3. Right click getActiveAndCompletedStats and select Generate > Test.

4. Select the test directory (not androidTest) because we'll be writing local tests.
Testing ViewModel
App Architecture Application

If our code was to be placed in Activity


only one place it will be hard to
be tested.
Fragment

Hence, following architecture will ViewModel


be a good solution.

Repository

Local Data source Remote Data Source


ToDo App Architecture.
The ToDo App follows
the MVVM architecture
which is the architecture
recommended by
Google.

Let’s start to test the


viewModel.
ToDo App Architecture.
TasksViewModel
You are going to focus on tests that have all their logic in the view
model and do not rely on repository code

The test you'll write will check that when you call the addNewTask
method, the Event for opening the new task window is fired. Here's the
app code you'll be testing
TasksViewModel

• Make a TasksViewModelTest class


• Create a new test called addNewTask_setsNewTaskEvent
TasksViewModel
Android ViewModel

AndroidViewModel is an Application context aware ViewModel.


Its Subclasses must have a constructor which accepts Application as the only
parameter.
Testing ViewModel
ViewModel is a class that shouldn't rely on the Android framework.

Hence, ViewModel Test usually doesn’t require running on a device it


runs locally. Also, Running it as a local test will be faster.

For AndroidViewModel it requires application Context. And the local


tests don’t offer such a context.

When we want to run a test as a local test but it requires a class from
android we can use AndroidX
AndroidX test
Collection of libraries for testing. It includes classes and methods that give
you test versions of components like applications and activities.

They are built to work both for local tests and instrumented tests. So:
• You can run the same test as a local test or an instrumented test.
• You don't need to learn different testing APIs for local vs. instrumented
tests.

When you write your code using AndroidX Test libraries, you can move it
from the test folder to the androidTest folder and the tests will still run.
Robolectric
Robolectric is a library that creates a simulated Android environment
for tests and runs faster than booting up an emulator or running on a
device.

The simulated Android environment that AndroidX Test uses for local
tests is provided by Robolectric.
Test Runner
• A test runner is a JUnit component that runs tests. Without a test
runner, your tests would not run. There's a default test runner provided
by JUnit that you get automatically. @RunWith swaps out that default
test runner.

• The AndroidJUnit4 test runner


allows for AndroidX Test to run
your test differently depending
on whether they are
instrumented or local tests.
Testing ViewModel Steps
1. Add AndroidX test dependencies
testImplementation “androidx.test:core-
ktx:$androidXTestCoreVersion” testImplementation
“androidx.test.ext:junit-
ktx:$androidXTestExtKotlinRunnerVersion”
1. Add Robolectric dependencies
testImplementation “org.robolectric:robolectric:4.8”
1. Swap out the default test runner
2. Use AndroidX to provide an android context for your viewModel
Testing ViewModel Steps
3

4
Testing LiveData
Observing LiveData in local test
We used to observe liveData. Without observation the value will be
null but to observe it we need a LifecycleOwner like activity or
fragment
which is not available here in local test.
How to solve this ??
the magic keyword is observeForever
which ensures the LiveData is constantly observed,
without needing a LifecycleOwner
Observing LiveData in local test Con.
Observation steps
1. Create observer
2. Observe livedata
3. Add new task
4. Assert livedata
5. Remove the observer Remember !!
Observing LiveData in local test Con.

1
2

5
Observing LiveData in local test Con.
• The previous solution works well. But every time we test the liveData
we will be creating the same dummy observer, handle it and finally
remove it. It seems like a Boilerplate code!

• To avoid using boilerplate code we can create a function that is in


charge of doing all the required handling and use it several time
through the application.

• It’s recommended to use the LiveDataTestUtil.


GetOrAwaitValue method
GetOrAwaitValue method Con.
addNewTask() final test
Labs
Labs
1. For the StatisticsUtils class you need to test the following
cases:
1. List with no completed tasks.
2. List with 2 completed tasks and 3 active tasks.
3. Empty list
4. Null (as a parameter)

2. For the TasksViewModel class you need to test the following


methods:
1. addNewTask()
2. setFilter() (private method)

You might also like