### Start AdbServer Desktop Source: https://github.com/kasperskylab/kaspresso/blob/master/README.md Instructions to start the AdbServer from the command line. Ensure you are in the Kaspresso directory and have the necessary JAR file. ```bash cd ~/Workspace/Kaspresso ``` ```bash java -jar artifacts/adbserver-desktop.jar ``` -------------------------------- ### Start AdbServer Source: https://github.com/kasperskylab/kaspresso/blob/master/samples/kaspresso-sample/src/main/assets/index.html Execute the adbserver-desktop.jar from the Kaspresso folder to start the AdbServer. This is required for most samples. ```bash java -jar artifacts/adbserver-desktop.jar ``` -------------------------------- ### Basic LoginActivity Test Setup Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Scenario.en.md Initial test setup to open the LoginActivity from the MainScreen. It uses Kaspresso's TestCase and step definitions. ```kotlin package com.kaspersky.kaspresso.tutorial import com.kaspersky.kaspresso.testcases.api.testcase.TestCase import com.kaspersky.kaspresso.tutorial.screen.MainScreen import org.junit.Test class LoginActivityTest : TestCase() { @Test fun test() { run { step("Open login screen") { MainScreen { loginActivityButton { isVisible() isClickable() click() } } } } } } ``` -------------------------------- ### Get ADB Server Help Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Executing_adb_commands.en.md Run this command to display all available options and flags for the `adbserver-desktop.jar` utility. ```bash java -jar adbserver-desktop.jar --help ``` -------------------------------- ### Full Test Example with Conditional Permission Handling Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Android_permissions.en.md This is a complete test case demonstrating how to handle runtime permissions across different Android API levels. It includes setup, UI interactions, and conditional permission acceptance. ```kotlin package com.kaspersky.kaspresso.tutorial import android.content.Context import android.media.AudioManager import android.os.Build import androidx.test.ext.junit.rules.activityScenarioRule import androidx.test.filters.SdkSuppress import com.kaspersky.kaspresso.testcases.api.testcase.TestCase import com.kaspersky.kaspresso.tutorial.screen.MainScreen import com.kaspersky.kaspresso.tutorial.screen.MakeCallActivityScreen import org.junit.Assert import org.junit.Rule import org.junit.Test class MakeCallActivityDevicePermissionsTest : TestCase() { @get:Rule val activityRule = activityScenarioRule() private val testNumber = "111" @Test fun checkSuccessCall() = before { }.after { device.phone.cancelCall(testNumber) }.run { step("Open make call activity") { MainScreen { makeCallActivityButton { isVisible() isClickable() click() } } } step("Check UI elements") { MakeCallActivityScreen { inputNumber.isVisible() inputNumber.hasHint(R.string.phone_number_hint) makeCallButton.isVisible() makeCallButton.isClickable() makeCallButton.hasText(R.string.make_call_btn) } } step("Try to call number") { MakeCallActivityScreen { inputNumber.replaceText(testNumber) makeCallButton.click() } } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { step("Accept permission") { device.permissions.apply { flakySafely { Assert.assertTrue(isDialogVisible()) ``` -------------------------------- ### Initial Test Setup for MakeCallActivity Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Android_permissions.en.md This is the initial test class setup for testing the MakeCallActivity, including activity rule and basic test steps. ```kotlin package com.kaspersky.kaspresso.tutorial import android.content.Context import android.media.AudioManager import androidx.test.ext.junit.rules.activityScenarioRule import com.kaspersky.kaspresso.testcases.api.testcase.TestCase import com.kaspersky.kaspresso.tutorial.screen.MainScreen import com.kaspersky.kaspresso.tutorial.screen.MakeCallActivityScreen import org.junit.Assert import org.junit.Rule import org.junit.Test class MakeCallActivityDevicePermissionsTest : TestCase() { @get:Rule val activityRule = activityScenarioRule() private val testNumber = "111" @Test fun checkSuccessCall() = before { }.after { device.phone.cancelCall(testNumber) }.run { step("Open make call activity") { MainScreen { makeCallActivityButton { isVisible() isClickable() click() } } } step("Check UI elements") { MakeCallActivityScreen { inputNumber.isVisible() inputNumber.hasHint(R.string.phone_number_hint) makeCallButton.isVisible() makeCallButton.isClickable() makeCallButton.hasText(R.string.make_call_btn) } } step("Try to call number") { MakeCallActivityScreen { inputNumber.replaceText(testNumber) makeCallButton.click() } } step("Check phone is calling") { flakySafely { val manager = device.context.getSystemService(Context.AUDIO_SERVICE) as AudioManager Assert.assertTrue(manager.mode == AudioManager.MODE_IN_CALL) } } } } ``` -------------------------------- ### Espresso UI Test Example Source: https://github.com/kasperskylab/kaspresso/blob/master/samples/kaspresso-sample/src/main/assets/index.html Standard Espresso syntax for performing UI interactions and checks. ```kotlin @Test fun testFirstFeature() { onView(withId(R.id.toFirstFeature)) .check(ViewAssertions.matches( ViewMatchers.withEffectiveVisibility( ViewMatchers.Visibility.VISIBLE))) onView(withId(R.id.toFirstFeature)).perform(click()) } ``` -------------------------------- ### Test with Before/After and Call Cancellation Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Android_permissions.en.md This example demonstrates using before and after blocks to manage test setup and teardown. The after block ensures that any ongoing phone call is cancelled, preventing resource leaks. ```kotlin private val testNumber = "111" @Test fun checkSuccessCall() = before { }.after { device.phone.cancelCall(testNumber) }.run { step("Open make call activity") { MainScreen { makeCallActivityButton { isVisible() isClickable() click() } } } step("Check UI elements") { MakeCallActivityScreen { inputNumber.isVisible() inputNumber.hasHint(R.string.phone_number_hint) makeCallButton.isVisible() makeCallButton.isClickable() makeCallButton.hasText(R.string.make_call_btn) } } step("Try to call number") { MakeCallActivityScreen { inputNumber.replaceText("111") makeCallButton.click() } } step("Check phone is calling") { flakySafely { val manager = device.context.getSystemService(Context.AUDIO_SERVICE) as AudioManager Assert.assertTrue(manager.mode == AudioManager.MODE_IN_CALL) } } } ``` -------------------------------- ### Install Allure Server on MacOS Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Kaspresso_Allure.en.md Install the Allure command-line tool on MacOS using Homebrew. This is required to generate and serve test reports. ```bash brew install allure ``` -------------------------------- ### Basic Test Structure Example Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/how_to_write_autotests.en.md A sample test demonstrating interaction with multiple screens and UI elements, including assertions with timeouts. ```kotlin @Test fun test() { MainScreen { nextButton { isVisible() click() } } SimpleScreen { button1 { click() } button2 { isVisible() } } SimpleScreen { button2 { click() } edit { attempt(timeoutMs = 7000) { isVisible() } hasText(R.string.text_edit_text) } } } ``` -------------------------------- ### Example Bug Report for Kaspresso Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Issues/index.en.md An example demonstrating how to fill out the bug report template, including specific error messages and reproduction steps related to library source downloads. ```text When using newer versions of the library, Gradle is unable to find and download the library sources (which allow you to read and debug the source code directly on the IDE). Expected Behavior Projects with the Kaspresso dependency should be able to download sources. Actual Behavior When trying do download sources, the following error appears: * What went wrong: Execution failed for task ':app:DownloadSources'. > Could not resolve all files for configuration ':app:downloadSources_10c6f7e9-408b-4f6a-8bd9-fe15e255981e'. > Could not find com.kaspersky.android-components:kaspresso:1.4.1@aar. Searched in the following locations: - https://dl.google.com/dl/android/maven2/com/kaspersky/android-components/kaspresso/1.4.1@aar/kaspresso-1.4.1@aar.pom - https://repo.maven.apache.org/maven2/com/kaspersky/android-components/kaspresso/1.4.1@aar/kaspresso-1.4.1@aar.pom Required by: project :app Steps to Reproduce the Problem Create an empty project; Add the dependency androidTestImplementation "com.kaspersky.android-components:kaspresso:1.4.1"; Create a test using classes from Kaspresso; Try to access the source (on IntelliJ IDE, Ctrl+left click a Kaspresso class name/method call); You will only be able to see the decompiled bytecode. Specifications Library version: at least >= 1.4.1 IDE used: Android Studio Observations I haven't tested on all versions, but sources were able to be downloaded at least up to version 1.2.1. ``` -------------------------------- ### Run AdbServer Desktop Client Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Executing_adb_commands.en.md Execute this command in your terminal to start the desktop part of the AdbServer. Ensure you replace '' with the actual path to your Kaspresso artifacts. ```bash java -jar /artifacts/adbserver-desktop.jar ``` -------------------------------- ### Start ADB Server with Custom Options Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Executing_adb_commands.en.md Use the `adbserver-desktop.jar` with specific flags to control emulator selection, port, logging level, ADB path, and command timeout. ```bash java -jar adbserver-desktop.jar -e emulator-5554,emulator-5556 -p 5041 -l VERBOSE ``` -------------------------------- ### Kakao UI Test Example Source: https://github.com/kasperskylab/kaspresso/blob/master/samples/kaspresso-sample/src/main/assets/index.html Kakao's Kotlin DSL for writing concise and readable UI tests. ```kotlin @Test fun testFirstFeature() { mainScreen { toFirstFeatureButton { isVisible() click() } } } ``` -------------------------------- ### Create a UiScreen Entity Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Kautomator-wrapper_over_UI_Automator.en.md Example of creating a custom UiScreen entity to represent a user interface or a portion of it. ```Kotlin class FormScreen : UiScreen() ``` -------------------------------- ### Kaspresso Test with Steps Source: https://github.com/kasperskylab/kaspresso/blob/master/README.md Kaspresso's extended DSL for structuring tests with steps, setup, and teardown. ```kotlin @Test fun shouldPassOnNoInternetScanTest() = beforeTest { activityTestRule.launchActivity(null) // some things with the state }.afterTest { // some things with the state }.run { step("Open Simple Screen") { MainScreen { nextButton { isVisible() click() } } } step("Click button_1 and check button_2") { SimpleScreen { button1 { click() } button2 { isVisible() } } } step("Click button_2 and check edit") { SimpleScreen { button2 { click() } edit { flakySafely(timeoutMs = 7000) { isVisible() } hasText(R.string.text_edit_text) } } } step("Check all possibilities of edit") { scenario( CheckEditScenario() ) } } ``` -------------------------------- ### Execute ADB shell command to list packages Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Working_with_adb.en.md Shows how to use `performShell` to list installed packages and verify if a specific package is present. Note that 'adb shell' prefix is not needed. ```kotlin val packages = adbServer.performShell("pm list packages") Assert.assertTrue("com.kaspersky.kaspresso.tutorial" in packages.first()) ``` -------------------------------- ### KScreen Implementation Example Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Page_object_in_Kaspresso.en.md Use KScreen for white-box testing when you have access to the application's source code. Initialize layoutId and viewClass for better refactoring support. ```kotlin object SimpleScreen : KScreen() { override val layoutId: Int? = R.layout.activity_simple override val viewClass: Class<*>? = SimpleActivity::class.java val button1 = KButton { withId(R.id.button_1) } val button2 = KButton { withId(R.id.button_2) } val edit = KEditText { withId(R.id.edit) } } ``` -------------------------------- ### UiScreen Implementation Example Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Page_object_in_Kaspresso.en.md Use UiScreen for black-box testing when you don't have access to the application's source code, such as system dialogs. The packageName field is mandatory. ```kotlin object MainScreen : UiScreen() { override val packageName: String = "com.kaspersky.kaspresso.kautomatorsample" val simpleEditText = UiEditText { withId(this@MainScreen.packageName, "editText") } val simpleButton = UiButton { withId(this@MainScreen.packageName, "button") } val checkBox = UiCheckBox { withId(this@MainScreen.packageName, "checkBox") } } ``` -------------------------------- ### Find Element by ID (Initial) Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/UiAutomator.en.md Demonstrates how to start defining an element using `withId` matcher. ```kotlin package com.kaspersky.kaspresso.tutorial.screen import com.kaspersky.components.kautomator.component.text.UiTextView import com.kaspersky.components.kautomator.screen.UiScreen object NotificationScreen : UiScreen() { override val packageName: String = "com.android.systemui" val title = UiTextView { withId("", "") } val content = UiTextView { withId("", "") } } ``` -------------------------------- ### Basic Espresso Interaction Example Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Matchers_actions_assertions.en.md Demonstrates a typical Espresso interaction: finding a view by ID, performing a click action, and asserting it's displayed. This pattern is fundamental for UI testing. ```kotlin onView(withId(R.id.my_view)) .perform(click()) .check(matches(isDisplayed())) ``` -------------------------------- ### Define Basic LoginScenario Class Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Scenario.en.md Create a new class that inherits from Kaspresso's `Scenario`. This is the initial setup for a reusable test flow. ```kotlin package com.kaspersky.kaspresso.tutorial import com.kaspersky.kaspresso.testcases.api.scenario.Scenario class LoginScenario : Scenario() { } ``` -------------------------------- ### Kautomator Interaction Example Source: https://github.com/kasperskylab/kaspresso/blob/master/samples/kaspresso-sample/src/main/assets/index.html Kautomator's Kotlin DSL for interacting with UI elements, mirroring Kakao's syntax. ```kotlin MainScreen { simpleEditText { replaceText("Kaspresso") hasText("Kaspresso") } } ``` -------------------------------- ### Full NoteListTest example Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Recyclerview.en.md A complete Kaspresso test case demonstrating the usage of Page Objects, including custom methods like swipeLeft, to verify the functionality of a note list screen. ```kotlin package com.kaspersky.kaspresso.tutorial import androidx.test.ext.junit.rules.activityScenarioRule import com.kaspersky.kaspresso.testcases.api.testcase.TestCase import com.kaspersky.kaspresso.tutorial.screen.MainScreen import com.kaspersky.kaspresso.tutorial.screen.NoteListScreen import org.junit.Assert import org.junit.Rule import org.junit.Test class NoteListTest : TestCase() { @get:Rule val activityRule = activityScenarioRule() @Test fun checkNotesScreen() = run { step("Open note list screen") { MainScreen { listActivityButton { isVisible() isClickable() click() } } } step("Check notes count") { NoteListScreen { Assert.assertEquals(3, rvNotes.getSize()) } } step("Check elements visibility") { NoteListScreen { rvNotes { children { tvNoteId.isVisible() tvNoteText.isVisible() noteContainer.isVisible() tvNoteId.hasAnyText() tvNoteText.hasAnyText() } } } } step("Check elements content") { NoteListScreen { rvNotes { childAt(0) { noteContainer.hasBackgroundColor(android.R.color.holo_green_light) tvNoteId.hasText("0") tvNoteText.hasText("Note number 0") } childAt(1) { noteContainer.hasBackgroundColor(android.R.color.holo_orange_light) tvNoteId.hasText("1") tvNoteText.hasText("Note number 1") } childAt(2) { noteContainer.hasBackgroundColor(android.R.color.holo_red_light) tvNoteId.hasText("2") tvNoteText.hasText("Note number 2") } } } } step("Check swipe to dismiss action") { NoteListScreen { rvNotes { childAt(0) { swipeLeft() device.uiDevice.waitForIdle() } Assert.assertEquals(2, getSize()) childAt(0) { noteContainer.hasBackgroundColor(android.R.color.holo_orange_light) tvNoteId.hasText("1") tvNoteText.hasText("Note number 1") } childAt(1) { noteContainer.hasBackgroundColor(android.R.color.holo_red_light) tvNoteId.hasText("2") tvNoteText.hasText("Note number 2") } } } } } } ``` -------------------------------- ### Run Screenshot Test with Before/After Blocks Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Pixel_by_pixel_comparison.en.md The runScreenshotTest function accepts optional 'before' and 'after' blocks for setup and teardown actions. ```kotlin @Test fun test() = runScreenshotTest( before = {}, after = {}, ) { // Test code } ``` -------------------------------- ### Example Test Using Scenario Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Scenario.en.md Demonstrates how to integrate a Scenario into a Kaspresso TestCase. The scenario is used within a 'run' block to execute a sequence of steps, including login. ```kotlin class AfterLoginActivityTest : TestCase() { @get:Rule val activityRule = activityScenarioRule() @Test fun test() { run { step("Open AfterLogin screen") { scenario( LoginScenario( username = "123456", password = "123456" ) ) } step("Check title") { AfterLoginScreen { title { isVisible() hasText(R.string.screen_after_login) } } } } } } ``` -------------------------------- ### Define a Compose Screen with Kakao Compose DSL Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Jetpack_Compose.en.md Example of creating a Screen class for Jetpack Compose UI elements using the Kakao Compose DSL. It demonstrates how to define parent-child relationships and use SemanticsNodeInteractionsProvider. ```kotlin // Screen class class ComposeMainScreen(semanticsProvider: SemanticsNodeInteractionsProvider) : ComposeScreen(semanticsProvider = semanticsProvider, // Screen in Kakao Compose can be a Node too due to 'viewBuilderAction' param. // 'viewBuilderAction' param is nullable. viewBuilderAction = { hasTestTag("ComposeMainScreen") } ) { // You can set clear parent-child relationship due to 'child' extension // Here, 'simpleFlakyButton' is a child of 'ComposeMainScreen' (that is Node too) val simpleFlakyButton: KNode = child { hasTestTag("main_screen_simple_flaky_button") } } ``` -------------------------------- ### Advanced Screenshot Test Sample Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Screenshot_tests.en.md An example of a screenshot test class that extends the base test case. It demonstrates setting up a fragment, obtaining a UI proxy, and capturing screenshots across multiple steps. ```kotlin @RunWith(AndroidJUnit4::class) class AdvancedScreenshotSampleTest : ProductDocLocScreenshotTestCase() { private lateinit var fragment: FeatureFragment private lateinit var view: FeatureView @ScreenShooterTest @Test fun test() { before { fragment = FeatureFragment() view = getUiSafeProxy(fragment as FeatureView) activity.setFragment(fragment) }.after { }.run { step("1. Step 1") { // ... [view] calls captureScreenshot("Step 1") } step("2. Step 2") { // ... [view] calls captureScreenshot("Step 2") } step("3. Step 3") { // ... [view] calls captureScreenshot("Step 3") } // ... other steps } } } ``` -------------------------------- ### DEBUG Log Example with Packed Repeating Information Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Executing_adb_commands.en.md Illustrates how DEBUG logs can consolidate repetitive information during connection attempts and service operations. Useful for diagnosing connection issues. ```text DEBUG 10/09/2020 12:11:37.006 desktop=Desktop-30548 device=emulator-5554 tag=DeviceMirror$WatchdogThread method=run message: The attempt to connect to Device. It may take time because the device can be not ready (for example, a kaspresso test was not started). DEBUG 10/09/2020 12:11:44.063 desktop=Desktop-30548 device=emulator-5554 tag=ServiceInfo method=Start message: ////////////////////////////////////////FRAGMENT IS REPEATED 7 TIMES//////////////////////////////////////// DEBUG 10/09/2020 12:11:44.064 desktop=Desktop-30548 device=emulator-5554 tag=ConnectionServerImplBySocket method=tryConnect message: Start the process DEBUG 10/09/2020 12:11:44.064 desktop=Desktop-30548 device=emulator-5554 tag=ConnectionMaker method=connect message: Start a connection establishment. The current state=DISCONNECTED DEBUG 10/09/2020 12:11:44.064 desktop=Desktop-30548 device=emulator-5554 tag=ConnectionMaker method=connect message: The current state=CONNECTING DEBUG 10/09/2020 12:11:44.064 desktop=Desktop-30548 device=emulator-5554 tag=DesktopDeviceSocketConnectionForwardImpl$getDesktopSocketLoad$1 method=invoke message: started with ip=127.0.0.1, port=37110 DEBUG 10/09/2020 12:11:44.064 desktop=Desktop-30548 device=emulator-5554 tag=DesktopDeviceSocketConnectionForwardImpl$getDesktopSocketLoad$1 method=invoke message: completed with ip=127.0.0.1, port=37110 DEBUG 10/09/2020 12:11:44.064 desktop=Desktop-30548 device=emulator-5554 tag=SocketMessagesTransferring method=prepareListening message: Start DEBUG 10/09/2020 12:11:44.064 desktop=Desktop-30548 device=emulator-5554 tag=ConnectionMaker method=connect message: The connection establishment process failed. The current state=DISCONNECTED DEBUG 10/09/2020 12:11:44.064 desktop=Desktop-30548 device=emulator-5554 tag=ConnectionServerImplBySocket$tryConnect$3 method=invoke message: The connection establishment attempt failed. The most possible reason is the opposite socket is not ready yet DEBUG 10/09/2020 12:11:44.064 desktop=Desktop-30548 device=emulator-5554 tag=DeviceMirror$WatchdogThread method=run message: The attempt to connect to Device. It may take time because the device can be not ready (for example, a kaspresso test was not started). DEBUG 10/09/2020 12:11:44.064 desktop=Desktop-30548 device=emulator-5554 tag=ServiceInfo method=End message: //////////////////////////////////////////////////////////////////////////////////////////////////// DEBUG 10/09/2020 12:11:44.064 desktop=Desktop-30548 device=emulator-5554 tag=ConnectionServerImplBySocket method=tryConnect message: Start the process DEBUG 10/09/2020 12:11:44.064 desktop=Desktop-30548 device=emulator-5554 tag=ConnectionMaker method=connect message: Start a connection establishment. The current state=DISCONNECTED ``` -------------------------------- ### Kaspresso Test Structure with State Management Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/how_to_write_autotests.en.md Demonstrates the standard Kaspresso test structure using `before`, `after`, and `run` blocks for state management. Use this for tests requiring setup and teardown of device state. ```kotlin ```kotlin @Test fun shouldPassOnNoInternetScanTest() = before { activityTestRule.launchActivity(null) // some things with the state }.after { // some things with the state }.run { step("Open Simple Screen") { MainScreen { nextButton { isVisible() click() } } } step("Click button_1 and check button_2") { SimpleScreen { button1 { click() } button2 { isVisible() } } } step("Click button_2 and check edit") { SimpleScreen { button2 { click() } edit { attempt(timeoutMs = 7000) { isVisible() } hasText(R.string.text_edit_text) } } } step("Check all possibilities of edit") { scenario( CheckEditScenario() ) } } ``` ``` -------------------------------- ### List Installed Packages via ADB Shell Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Working_with_adb.en.md While inside the ADB shell, use this command to get a list of all applications installed on the device. ```bash pm list packages ``` -------------------------------- ### Testing for Expected Failure Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Writing_simple_test.en.md Implement checks to ensure tests fail when conditions are not met, verifying the test's accuracy. This example snippet is incomplete and intended to demonstrate the start of a failure test. ```kotlin class SimpleActivityTest : TestCase() { @get:Rule val activityRule = activityScenarioRule() @Test fun test() { MainScreen { simpleActivityButton { ``` -------------------------------- ### Initialize Test Class and Navigate to Note List Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Recyclerview.en.md Sets up the test class and navigates to the NoteListScreen from the MainScreen. Requires `activityScenarioRule` for activity launching. ```kotlin package com.kaspersky.kaspresso.tutorial import androidx.test.ext.junit.rules.activityScenarioRule import com.kaspersky.kaspresso.testcases.api.testcase.TestCase import com.kaspersky.kaspresso.tutorial.screen.MainScreen import org.junit.Rule import org.junit.Test class NoteListTest : TestCase() { @get:Rule val activityRule = activityScenarioRule() @Test fun checkNotesScreen() = run { step("Open note list screen") { MainScreen { listActivityButton { isVisible() isClickable() click() } } } } } ``` -------------------------------- ### Kaspresso Test with Before and After Sections Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Steps_and_sections.en.md Use `before` to set up the initial device state (portrait orientation, Wi-Fi enabled) and `after` to reset it. The `run` block contains the test steps. ```kotlin package com.kaspersky.kaspresso.tutorial import androidx.test.ext.junit.rules.activityScenarioRule import com.kaspersky.kaspresso.device.exploit.Exploit import com.kaspersky.kaspresso.testcases.api.testcase.TestCase import com.kaspersky.kaspresso.tutorial.screen.MainScreen import com.kaspersky.kaspresso.tutorial.screen.WifiScreen import org.junit.Rule import org.junit.Test class WifiSampleWithStepsTest : TestCase() { @get:Rule val activityRule = activityScenarioRule() @Test fun test() { before { /** * Set portrait orientation and enable Wifi before the test */ device.exploit.setOrientation(Exploit.DeviceOrientation.Portrait) device.network.toggleWiFi(true) }.after { /** * Reset the default state after the test */ device.exploit.setOrientation(Exploit.DeviceOrientation.Portrait) device.network.toggleWiFi(true) }.run { step("Open target screen") { MainScreen { wifiActivityButton { isVisible() isClickable() click() } } } step("Check correct wifi status") { WifiScreen { checkWifiButton.isVisible() checkWifiButton.isClickable() wifiStatus.hasEmptyText() checkWifiButton.click() wifiStatus.hasText(R.string.enabled_status) device.network.toggleWiFi(false) checkWifiButton.click() wifiStatus.hasText(R.string.disabled_status) } } step("Rotate device and check wifi status") { WifiScreen { device.exploit.rotate() wifiStatus.hasText(R.string.disabled_status) } } } } } ``` -------------------------------- ### Build adbserver-desktop.jar Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Executing_adb_commands.en.md Execute this command to manually build the adbserver-desktop.jar file. Ensure you are in the project root directory. ```bash ./gradlew :adb-server:adbserver-desktop:assemble ``` -------------------------------- ### Screenshot Metadata XML Example Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Screenshot_tests.en.md An example of the XML file generated alongside screenshots, containing UI element information and their localized values. ```xml ``` -------------------------------- ### Full Test Case with Permission Granting Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Android_permissions.en.md This example demonstrates a complete test case that includes setting up the GrantPermissionRule, launching an activity, interacting with UI elements, and asserting the expected outcome. Remember to revoke permissions or uninstall the app before running. ```kotlin package com.kaspersky.kaspresso.tutorial import android.content.Context import android.media.AudioManager import androidx.test.ext.junit.rules.activityScenarioRule import androidx.test.rule.GrantPermissionRule import com.kaspersky.kaspresso.testcases.api.testcase.TestCase import com.kaspersky.kaspresso.tutorial.screen.MainScreen import com.kaspersky.kaspresso.tutorial.screen.MakeCallActivityScreen import org.junit.Assert import org.junit.Rule import org.junit.Test class MakeCallActivityTest : TestCase() { @get:Rule val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant( android.Manifest.permission.CALL_PHONE ) @get:Rule val activityRule = activityScenarioRule() @Test fun checkSuccessCall() = run { step("Open make call activity") { MainScreen { makeCallActivityButton { isVisible() isClickable() click() } } } step("Check UI elements") { MakeCallActivityScreen { inputNumber.isVisible() inputNumber.hasHint(R.string.phone_number_hint) makeCallButton.isVisible() makeCallButton.isClickable() makeCallButton.hasText(R.string.make_call_btn) } } step("Try to call number") { MakeCallActivityScreen { inputNumber.replaceText("111") makeCallButton.click() } } step("Check phone is calling") { val manager = device.context.getSystemService(Context.AUDIO_SERVICE) as AudioManager Assert.assertTrue(manager.mode == AudioManager.MODE_IN_CALL) } } } ``` -------------------------------- ### Implement Login Scenario Steps Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Scenario.en.md Define the sequence of steps for the login scenario, including opening the login screen, checking element visibility, and attempting to log in. This uses Kaspresso's DSL for defining UI interactions. ```kotlin package com.kaspersky.kaspresso.tutorial import com.kaspersky.kaspresso.testcases.api.scenario.Scenario import com.kaspersky.kaspresso.testcases.core.testcontext.TestContext import com.kaspersky.kaspresso.tutorial.screen.LoginScreen import com.kaspersky.kaspresso.tutorial.screen.MainScreen class LoginScenario : Scenario() { override val steps: TestContext.() -> Unit = { step("Open login screen") { MainScreen { loginActivityButton { isVisible() isClickable() click() } } } step("Check elements visibility") { LoginScreen { inputUsername { isVisible() hasHint(R.string.login_activity_hint_username) } inputPassword { isVisible() hasHint(R.string.login_activity_hint_password) } loginButton { isVisible() isClickable() } } } step("Try to login") { LoginScreen { inputUsername { replaceText(username) } inputPassword { replaceText(password) } loginButton { click() } } } } } ``` -------------------------------- ### UI Automator Interaction Example Source: https://github.com/kasperskylab/kaspresso/blob/master/samples/kaspresso-sample/src/main/assets/index.html Direct interaction with UI elements using UI Automator API. ```kotlin val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() val uiDevice = UiDevice.getInstance(instrumentation) val uiObject = uiDevice.wait( Until.findObject( By.res( "com.kaspersky.kaspresso.sample_kautomator", "editText" ) ), 2_000 ) uiObject.text = "Kaspresso" assertEquals(uiObject.text, "Kaspresso") ``` -------------------------------- ### Kaspresso Example Comment Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Kaspresso_configuration.en.md A simple comment indicating a section of code or a note within the Kaspresso framework. ```text Pretty good. ``` -------------------------------- ### Execute CMD command and check result Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Working_with_adb.en.md Demonstrates running a command-line command like 'hostname' using `performCmd` and asserting that the result is not empty. ```kotlin val hostname = adbServer.performCmd("hostname") Assert.assertTrue(hostname.isNotEmpty()) ``` -------------------------------- ### Combine Matchers for UiEditText Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Kautomator-wrapper_over_UI_Automator.en.md Example of combining multiple matchers (withId and withText) to precisely locate a UiEditText element. ```Kotlin val email = UiEditText { withId(this@FormScreen.packageName, "email") withText(this@FormScreen.packageName, "matsyuk@kaspresso.com") } ``` -------------------------------- ### Granting CALL_PHONE Permission Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Android_permissions.en.md This rule automatically grants the CALL_PHONE permission before the test starts. Ensure this permission is declared in your AndroidManifest.xml. ```kotlin val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant( android.Manifest.permission.CALL_PHONE ) ``` -------------------------------- ### Compose Test Setup and DSL Usage Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Jetpack_Compose.en.md Illustrates setting up a Jetpack Compose test with Kaspresso, including the necessary JUnit runner, Kaspresso builder, and Compose test rule. It shows how to use the Kaspresso test DSL to interact with Compose UI elements. ```kotlin // This annotation is here to make the test is appropriate for JVM environment (with Robolectric) @RunWith(AndroidJUnit4::class) // Test class declaration class ComposeSimpleFlakyTest : TestCase( kaspressoBuilder = Kaspresso.Builder.withComposeSupport() ) { // Special rule for Compose tests @get:Rule val composeTestRule = createAndroidComposeRule() // Test DSL. It's so similar to Kakao or Kautomator DSL @Test fun test() = run { step("Open Flaky screen") { onComposeScreen(composeTestRule) { simpleFlakyButton { assertIsDisplayed() performClick() } } } step("Click on the First button") { onComposeScreen(composeTestRule) { firstButton { assertIsDisplayed() performClick() } } } // ... } } ``` -------------------------------- ### Logging Semantics Watcher Interceptor Logs Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Jetpack_Compose.en.md Example output from the LoggingSemanticsWatcherInterceptor, showing detailed test step logs and interaction details. ```kotlin I/KASPRESSO: TEST STEP: "1. Open Flaky screen" in ComposeSimpleFlakyTest SUCCEED. It took 0 minutes, 0 seconds and 212 millis. I/KASPRESSO: ___________________________________________________________________________ I/KASPRESSO: ___________________________________________________________________________ I/KASPRESSO: TEST STEP: "2. Click on the First button" in ComposeSimpleFlakyTest I/KASPRESSO: Operation: Check=IS_DISPLAYED(description={null}). ComposeInteraction: matcher: (hasParentThat(TestTag = 'simple_flaky_screen_container')) && (TestTag = 'simple_flaky_screen_simple_first_button'); position: 0; useUnmergedTree: false. I/KASPRESSO: Reloading of the element is started I/KASPRESSO: Reloading of the element is finished I/KASPRESSO: Repeat action again with the reloaded element I/KASPRESSO: Operation: Check=IS_DISPLAYED(description={null}). ComposeInteraction: matcher: (hasParentThat(TestTag = 'simple_flaky_screen_container')) && (TestTag = 'simple_flaky_screen_simple_first_button'); position: 0; useUnmergedTree: false. I/KASPRESSO: SemanticsNodeInteraction autoscroll successfully performed. I/KASPRESSO: Operation: Check=IS_DISPLAYED(description={null}). ComposeInteraction: matcher: (hasParentThat(TestTag = 'simple_flaky_screen_container')) && (TestTag = 'simple_flaky_screen_simple_first_button'); position: 0; useUnmergedTree: false. I/KASPRESSO: Operation: Perform=PERFORM_CLICK(description={null}). ComposeInteraction: matcher: (hasParentThat(TestTag = 'simple_flaky_screen_container')) && (TestTag = 'simple_flaky_screen_simple_first_button'); position: 0; useUnmergedTree: false. I/KASPRESSO: TEST STEP: "2. Click on the First button" in ComposeSimpleFlakyTest SUCCEED. It took 0 minutes, 0 seconds and 123 millis. I/KASPRESSO: ___________________________________________________________________________ I/KASPRESSO: ___________________________________________________________________________ I/KASPRESSO: TEST STEP: "3. Click on the Second button" in ComposeSimpleFlakyTest ``` -------------------------------- ### Launching Google Play Activity Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/UiAutomator.en.md Launches the Google Play application's main screen by starting the activity associated with the obtained Intent. ```kotlin val intent = device.targetContext.packageManager.getLaunchIntentForPackage(GOOGLE_PLAY_PACKAGE) device.targetContext.startActivity(intent) ``` -------------------------------- ### Execute ADB command using performCmd Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Working_with_adb.en.md Illustrates using `performCmd` to execute an ADB command, requiring the full 'adb devices' syntax. This is an alternative to `performAdb`. ```kotlin val result = adbServer.performCmd("adb devices") Assert.assertTrue("emulator" in result.first()) ``` -------------------------------- ### Create Basic WifiSampleTest Class Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Wifi_sample_test.en.md Initialize a new test class that inherits from Kaspresso's TestCase. This class will contain the test methods for Wi-Fi functionality. ```kotlin package com.kaspersky.kaspresso.tutorial import com.kaspersky.kaspresso.testcases.api.testcase.TestCase class WifiSampleTest: TestCase() { } ``` -------------------------------- ### Test for AfterLoginActivity Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Scenario.en.md A basic test class structure for AfterLoginActivity, demonstrating how to set up tests that might require prior navigation or setup, such as through a Scenario. ```kotlin package com.kaspersky.kaspresso.tutorial import androidx.test.ext.junit.rules.activityScenarioRule import com.kaspersky.kaspresso.testcases.api.testcase.TestCase import org.junit.Rule import org.junit.Test class AfterLoginActivityTest : TestCase() { @get:Rule val activityRule = activityScenarioRule() @Test fun test() { } } ``` -------------------------------- ### Getting Launch Intent for Google Play Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/UiAutomator.en.md Retrieves the Intent object required to launch the Google Play application using its package name. ```kotlin val intent = device.targetContext.packageManager.getLaunchIntentForPackage(GOOGLE_PLAY_PACKAGE) ``` -------------------------------- ### Write UI Interactions with Kautomator Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Wiki/Kautomator-wrapper_over_UI_Automator.en.md Demonstrates writing UI interactions and assertions using the Kautomator DSL after defining UiScreen and UiView elements. ```Kotlin FormScreen { phone { hasText("971201771") } button { click() } } ``` -------------------------------- ### Check AudioManager Mode in Call Source: https://github.com/kasperskylab/kaspresso/blob/master/docs/Tutorial/Android_permissions.en.md Verifies that the device's audio mode is set to 'IN_CALL' after an action, typically used to confirm a call has started. ```kotlin step("Check phone is calling") { val manager = device.context.getSystemService(AudioManager::class.java) Assert.assertTrue(manager.mode == AudioManager.MODE_IN_CALL) } ```