Screenshot Kata for Android Developers with Kotlin. The main goal is to practice UI Screenshot Testing.

Overview

Karumi logo KataScreenshot in Kotlin Build Status

You can compare this testing approach with a different testing strategy where the application UI is tested using just Espresso.


Getting started

This repository contains an Android application to show Super Heroes information:

ApplicationScreencast

This Application is based on two Activities:

  • MainActivity showing a list of super heroes with name, photo and a special badge if it is part of the Avengers Team.

MainActivityScreenhot

  • SuperHeroDetailActivity showing detailed information about a super hero like his or her name, photo and description.

SuperHeroDetailActivityScreenshot

The application architecture, dependencies and configuration is ready to just start writing tests. In this project you'll find Kodein configured to be able to replace production code with test doubles easily and Espresso to be able to interact with the application user interface and a screenshot testing framework ready to compare your application changes.

Remember that after any production code change you can record your screenshots again executing:

./gradlew executeScreenshotTests -Precord

To verify the correct behaviour of your code you can execute:

./gradlew executeScreenshotTests

To be able to get a deterministic test scenario all our tests will be executed on the same emulated device. You can use the Travis-CI configuration to get the same emulator working on your computer.

Tasks

Your task as Android Developer is to write all the UI tests needed to check if the Application UI is working as expected.

This repository is ready to build the application, pass the checkstyle and your tests in Travis-CI environments.

Our recommendation for this exercise is:

  • Before starting

    1. Fork this repository.
    2. Checkout kata-screenshot branch.
    3. Execute the application, explore it manually and make yourself familiar with the code.
    4. Execute MainActivityTest and watch the only test it contains pass.
  • To help you get started, these are some test cases for MainActivity:

    1. Setup mocked SuperHeroRepository in MainActivityTest to return a list of some Super Heroes.
    2. Test the MainActivity is showing the super heroes obtained from the SuperHeroesRepository.
    3. Test the empty case is shown if there are no super heroes.

Considerations

  • If you get stuck, master branch contains already solved tests for MainActivity, SuperHeroDetailActivity and SuperHeroViewHolder.

Extra Tasks

If you've covered all the application functionality using UI tests try to continue with the following tasks:

  • Add a pull to refresh mechanism to MainActivity and test it.
  • Modify SuperHeroDetailActivity to handle an error case where the name of the super hero used to start this activity does not exist and show a message if this happens.
  • Modify the project to handle connection errors and show a SnackBar to indicate something went wrong.
  • Modify SuperHeroesRepository test double to perform a Thread.sleep and use the custom idling resources you'll find in this repository to get your tests working.
  • Compare your tests implementation with the KataSuperHeroes solved using Espresso.

Documentation

There are some links which can be useful to finish these tasks:

Data provided by Marvel. © 2017 MARVEL

License

Copyright 2017 Karumi

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Comments
  • Add presenter

    Add presenter

    The scope of this pull request is setting the first version of MVP for the superhero kata.

    The idea is you can start to review the DI code, Presenter code and invocation between them.

    I will update the PR with a small test.

    opened by flipper83 3
  • Add usecase repository

    Add usecase repository

    This pull request contains the first commit with information come from use cases. I like update the PR step by steps because I have some code that I like your approval :)

    This first commit contains usercases, list representation and resultValues. Next commit will contains a list test and travis configuration. After that I will start working on repository code.

    opened by flipper83 1
  • Travis CI build failing and .iml files pushed up

    Travis CI build failing and .iml files pushed up

    opened by albodelu 0
  • Show the activity title with the appcompat toolbar

    Show the activity title with the appcompat toolbar

    :pushpin: References

    • Issue: #5

    :cyclone: Git merge message

    • Install the support toolbar in every activity through the BaseActivity class
    • Configure the toolbar title in the super hero detail view to show the super hero name
    • Remove error handling and funktional.either dependency as it's one of the extra task we are asking for in the kata.

    :memo: Notes

    • It's oddly satisfying to see how the two katas now produce the same screenshots 😅
    • I'll cherry-pick this PR into kata-screenshot branch BTW
    opened by Serchinastico 0
  • Super hero cell tests

    Super hero cell tests

    :pushpin: References

    • Issue: #4

    :cyclone: Git merge message

    • Create a ScreenshotTest trait with methods to verify that views/activities/viewholders are correct by using the Facebook library. The logic has been extracted from the previous AcceptanceTest class so that it can be used with non-activity tests
    • Create screenshot tests for super hero cells by just porting it from our Java implementation
    • Fix some typos in the travis configuration file

    :memo: Notes

    • There are some other minor style changes, don't even bother with those if you don't want to
    opened by Serchinastico 0
  • java.nio.file.NoSuchFileExceptio

    java.nio.file.NoSuchFileExceptio

    On Windows 10 x64 + AS 3.4.1

    run task executeScreenshotTests always encounter this exception

    It works fine on OSX but Windows at least I try it on 2 PCs The compare files will be placed correctly, but all the file size is 0

    Exception is:

    Caused by: org.gradle.api.UncheckedIOException: java.nio.file.NoSuchFileException: \tmp\shot\screenshot\app\com.entertainment.MainActivityTest_testScreenshotEntireActivity.png at org.gradle.internal.UncheckedException.throwAsUncheckedException(UncheckedException.java:61) at org.gradle.internal.UncheckedException.throwAsUncheckedException(UncheckedException.java:41) at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:76) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:48) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:41) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:28) at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:704) at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:671) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$2.run(ExecuteActionsTaskExecuter.java:284) at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:301) at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:293) at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175) at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91) at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:273) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:258) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access$200(ExecuteActionsTaskExecuter.java:67) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:145) at org.gradle.internal.execution.impl.steps.ExecuteStep.execute(ExecuteStep.java:49) at org.gradle.internal.execution.impl.steps.CancelExecutionStep.execute(CancelExecutionStep.java:34) at org.gradle.internal.execution.impl.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:69) at org.gradle.internal.execution.impl.steps.TimeoutStep.execute(TimeoutStep.java:49) at org.gradle.internal.execution.impl.steps.CatchExceptionStep.execute(CatchExceptionStep.java:33) at org.gradle.internal.execution.impl.steps.CreateOutputsStep.execute(CreateOutputsStep.java:50) at org.gradle.internal.execution.impl.steps.SnapshotOutputStep.execute(SnapshotOutputStep.java:43) at org.gradle.internal.execution.impl.steps.SnapshotOutputStep.execute(SnapshotOutputStep.java:29) at org.gradle.internal.execution.impl.steps.CacheStep.executeWithoutCache(CacheStep.java:134) at org.gradle.internal.execution.impl.steps.CacheStep.lambda$execute$3(CacheStep.java:83) at org.gradle.internal.execution.impl.steps.CacheStep.execute(CacheStep.java:82) at org.gradle.internal.execution.impl.steps.CacheStep.execute(CacheStep.java:36) at org.gradle.internal.execution.impl.steps.PrepareCachingStep.execute(PrepareCachingStep.java:33) at org.gradle.internal.execution.impl.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:38) at org.gradle.internal.execution.impl.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:23) at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:96) at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:89) at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:52) at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:36) at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:34) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:91)

    opened by frog1014 0
Owner
Karumi
Karumi, the Rock Solid Code studio
Karumi
Super Heroes Kata for Android Developers in Kotlin. The main goal is to practice UI Testing.

KataSuperHeroes in Kotlin We are here to practice UI Testing. We are going to use Espresso to interact with the Application UI. We are going to use Ko

Karumi 86 Nov 20, 2022
Maxibon kata for Kotlin Developers. The main goal is to practice property based testing.

Kata Maxibon for Kotlin. We are here to practice property based testing. We are going to use KotlinTest to write our tests. We are going to practice p

Karumi 44 Oct 3, 2022
TODO API Client Kata for Kotlin Developers. The main goal is to practice integration testing using MockWebServer

KataTODOApiClient for Kotlin We are here to practice integration testsing using HTTP stubbing. We are going to use MockWebServer to simulate a HTTP se

Karumi 61 Nov 20, 2022
KataContacts written in Kotlin. The main goal is to practice Clean Architecture Development

KataContacts written in Kotlin We are here to practice Clean Architecture Development. Clean Architecture is a way of structuring code. We are going t

Karumi 48 Oct 3, 2022
🔥The Android Startup library provides a straightforward, performant way to initialize components at the application startup. Both library developers and app developers can use Android Startup to streamline startup sequences and explicitly set the order of initialization.

??The Android Startup library provides a straightforward, performant way to initialize components at the application startup. Both library developers and app developers can use Android Startup to streamline startup sequences and explicitly set the order of initialization.

Rouse 1.3k Dec 30, 2022
A reliable android app that shows upcoming fixtures, updated league tables, and top goal scorers in a league

SwiftScore A football stats and livescore app built with Kotlin,MVVM architecture,Retrofit, Coroutines and Navigation Components Demo Screenshots API

Breens Mbaka 12 Jul 7, 2022
The home of the amigo-platform which serves as the main service for the amigo multimedia platform

amigo-platform This is the home of the amigo-platform which serves as the main service for the amigo multimedia platform. Authentication with JWT Toke

null 1 Nov 22, 2021
This app works as a simple replacement for SpongeAuth for those who want to use Discourse as the main SSO auth provider.

PowerNukkit Ore to Discourse Auth Gateway This app works as a simple replacement for SpongeAuth for those who want to use Discourse as the main SSO au

null 1 Apr 9, 2022
Candroid does things different. The Candroid app store is a library of APK client wrappers (F-Droid, APKPure, etc.) For the main Candroid app store, try visiting the Candroid Market.

Candroid App Store Candroid does things different. The Candroid app store is a library of APK client wrappers (F-Droid, APKPure, etc.) For the main Ca

Sean P. Myrick V19.1.7.2 4 Dec 22, 2022
Basic RestAPI to practice my skills working with Spring/Kotlin/Gradle

Dining Review API Dining Review API is a basic RestAPI roughly based on the requirements given in a Milestone project in the Building REST APIs with J

Jonas Kuhlo 0 Nov 18, 2021
This is a practice app. An app that you can find random recipes and choose the ones you like.

A food suggestion app like Tinder This is a practice app. In this app, you can find random recipes and choose the ones you like. This is main menu. Yo

Yunus Emre OCAK 4 May 25, 2022
Solutions to Hackerrank and CoderByte practice problems

Solutions to Hackerrank and CoderByte practice problems This repository contains solutions to CoderByte and Hackerrank practice problems with Kotlin.

Mert Toptas 2 Jul 5, 2022
PlaceAutoComplete - Practice Repository for placesearch using google places Api

PlaceAutoComplete Practice Repository for placesearch using google places Api Ap

Nayeem Shiddiki Abir 0 Jan 1, 2022
In this single activity app. i was trying to practice on ViewModel and Livedata

CalwithViewModel In this single activity app. i was trying to practice on ViewModel and Livedata Min Api Level : 19 Setup Requirements Android device

Tech_G 1 Feb 16, 2022
An library to help android developers working easly with activities and fragments (Kotlin version)

AFM An library to help android developer working easly with activities and fragments (Kotlin) Motivation Accelerate the process and abstract the logic

Massive Disaster 12 Oct 3, 2022
A pragmatic lightweight dependency injection framework for Kotlin developers.

A pragmatic lightweight dependency injection framework for Kotlin developers. Koin is a DSL, a light container and a pragmatic API

insert-koin.io 11 Dec 14, 2022
Code for the Advanced Android Kotlin Testing Codelab 5.1-5.3

TO-DO Notes - Code for 5.1-5.3 Testing Codelab Code for the Advanced Android Kotlin Testing Codelab 5.1-5.3 Introduction TO-DO Notes is an app where y

Jorge M 1 Jun 7, 2022
Kotlin Unit Testing Examples

Kotlin Unit Testing Examples Table of Contents Application Gradle, Kotlin & Groovy Junit4 Junit5 KotlinTest Spek Mockito Mockito-Kotlin Mockk Strikt T

Jarosław 110 Dec 11, 2022