Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Screenshot tests edited #564

Merged
merged 50 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
4a390ca
TECH: add screenshot-tests-1 lesson
sumin93 Jun 2, 2023
2a80524
TECH: update tutorial branch
sumin93 Jun 2, 2023
2e78bea
TECH: update tutorial
sumin93 Jun 2, 2023
1d138ab
TECH: update tutorial
sumin93 Jun 2, 2023
67973e5
TECH: update tutorial
sumin93 Jun 2, 2023
94ddc13
TECH: update tutorial
sumin93 Jun 2, 2023
7b3cfd0
TECH: update tutorial
sumin93 Jun 2, 2023
0714a5d
TECH: change build branch
sumin93 Jun 27, 2023
06140bd
TECH: minor changes to review lessons logger and screenshots
sumin93 Jun 28, 2023
f8cf670
TECH: minor changes to review lessons logger and screenshots
sumin93 Jun 28, 2023
42cb800
TECH: minor changes to review lessons logger and screenshots
sumin93 Jun 28, 2023
c51c942
TECH: changes in screenshot lesson
sumin93 Jul 5, 2023
37b379f
TECH: changes in screenshot lesson
sumin93 Jul 5, 2023
57a2489
TECH: changes in screenshot lesson
sumin93 Jul 5, 2023
645d693
TECH: changes in screenshot lesson
sumin93 Jul 5, 2023
3077619
TECH: changes in screenshot lesson
sumin93 Jul 6, 2023
3c7e92f
TECH: changes in screenshot lesson
sumin93 Jul 10, 2023
cdd0bf8
TECH: changes in screenshot lesson
sumin93 Jul 10, 2023
57c0b79
TECH: changes in screenshot lesson
sumin93 Jul 10, 2023
cc7f049
TECH: changes in screenshot lesson
sumin93 Jul 10, 2023
8d64661
TECH: changes in screenshot lesson
sumin93 Jul 13, 2023
1901405
TECH: changes in screenshot lesson
sumin93 Jul 13, 2023
8933ea8
TECH: changes in screenshot lesson
sumin93 Jul 13, 2023
429d1d8
TECH: changes in screenshot lesson
sumin93 Jul 13, 2023
b11a760
TECH: screenshot tests lesson
sumin93 Jul 18, 2023
5076144
TECH: screenshot tests lesson
sumin93 Jul 18, 2023
eb7712a
TECH: screenshot tests lesson
sumin93 Jul 18, 2023
c3b577d
TECH: screenshot tests lesson
sumin93 Jul 18, 2023
f86684a
TECH: screenshot tests lesson
sumin93 Jul 18, 2023
a745a8d
TECH: screenshot tests lesson
sumin93 Jul 18, 2023
913f327
TECH: screenshot tests lesson
sumin93 Jul 24, 2023
20bd02e
TECH: screenshot tests lesson
sumin93 Aug 14, 2023
64b6b59
TECH: screenshot tests lesson
sumin93 Aug 14, 2023
f6d5f91
TECH: screenshot tests lesson
sumin93 Aug 14, 2023
5e52cbd
TECH: screenshot tests lesson
sumin93 Aug 14, 2023
341c50b
Update tutorial.yml
AzamatCherchesov Aug 21, 2023
8847379
TECH: change english version
sumin93 Aug 24, 2023
2706c49
TECH: edit Screenshot_tests_2.en.md
sumin93 Aug 31, 2023
3240712
TECH: edit Screenshot_tests_2.en.md
sumin93 Aug 31, 2023
28ef60a
Revert "TECH: edit Screenshot_tests_2.en.md"
sumin93 Aug 31, 2023
33308aa
TECH: edit Screenshot_tests_2.en.md
sumin93 Aug 31, 2023
f6fdfda
TECH: edit Screenshot_tests_2.en.md
sumin93 Aug 31, 2023
f30bf30
Revert "TECH: edit Screenshot_tests_2.en.md"
sumin93 Aug 31, 2023
95a1e52
TECH: edit Screenshot_tests_2.en.md
sumin93 Aug 31, 2023
1c07e06
TECH: edit Screenshot_tests_2.en.md
sumin93 Aug 31, 2023
bb9ffac
TECH: fix english version
sumin93 Aug 31, 2023
7237223
TECH: fix english version
sumin93 Aug 31, 2023
857f20a
TECH: return build on master branch
sumin93 Aug 31, 2023
d679579
Merge branch 'master' into TECH-tutorial
AzamatCherchesov Oct 9, 2023
f1e74b4
TECH: rolled back some changes
AzamatCherchesov Oct 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 25 additions & 48 deletions docs/Tutorial/Screenshot_tests_1.en.md

Large diffs are not rendered by default.

44 changes: 27 additions & 17 deletions docs/Tutorial/Screenshot_tests_2.en.md

Large diffs are not rendered by default.

33 changes: 21 additions & 12 deletions docs/Tutorial/Screenshot_tests_2.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class LoadUserScreenshots : DocLocScreenshotTestCase(locales = "en, fr") {

@Test
fun takeScreenshots() {

}
}

Expand Down Expand Up @@ -191,6 +191,8 @@ class LoadUserScreenshots : DocLocScreenshotTestCase(locales = "en, fr") {

```

На этом этапе уже можно видеть одну проблему - мы загружаем данные из сети, в зависимости от скорости интернета и от работоспособности сервера скорость загрузки может меняться. Есть большая вероятность, что данные о пользователе будут загружены почти мгновенно, и состояние загрузки вы вообще не увидите, оно не будет сохранено на скриншотах, и тест упадет, потому что проверка на `progressBarLoading.isVisible` никогда не вернет значение true. Решение этой проблемы мы разберем далее в этом уроке.

Следующий этап – отображение данных о пользователе (стейт Content)

```kotlin
Expand Down Expand Up @@ -223,7 +225,7 @@ class LoadUserScreenshots : DocLocScreenshotTestCase(locales = "en, fr") {
}

```
Теперь нам нужно получить состояние ошибки. В реальных приложениях можно было бы, например, выключить интернет на устройстве и выполнить запрос. В текущей реализации приложения мы лишь имитируем работу с интернетом, и для получения ошибки можно еще дважды попробовать загрузить данные пользователя. Имейте в виду, что это временная реализация, позже мы ее исправим.
Теперь нам нужно получить состояние ошибки. Как вариант, мы можем отключить интернет на устройстве, затем кликнуть по кнопке и увидеть сообщение об ошибке. Тогда нужно не забывать перед проведением тестирования, а также после него включать интернет, чтобы наш тест всегда запускался в необходимых условиях, а также не влиял на другие тесты. После включения и выключения теста добавим небольшой таймаут, чтобы быть уверенным, что интернет-подключение перешло в нужное нам состояние.

```kotlin
package com.kaspersky.kaspresso.tutorial.screenshot_tests
Expand All @@ -243,43 +245,45 @@ class LoadUserScreenshots : DocLocScreenshotTestCase(locales = "en, fr") {
@Test
fun takeScreenshots() {
LoadUserScreen {
device.network.enable()
Thread.sleep(5000)
loadingButton.isVisible()
captureScreenshot("Initial state")
loadingButton.click()
progressBarLoading.isVisible()
captureScreenshot("Progress state")
username.isVisible()
captureScreenshot("Content state")
device.network.disable()
Thread.sleep(3000)
loadingButton.click()
progressBarLoading.isVisible()
username.isVisible()
loadingButton.click()
progressBarLoading.isVisible()
error.isVisible()
captureScreenshot("Error state")
device.network.enable()
Thread.sleep(5000)
}
}
}

```


## Проблемы текущего подхода

Таким образом, мы смогли написать скриншот тест, в котором получили все необходимые состояния экрана, имитируя действия пользователя – кликая по кнопке и ожидая результата выполнения запроса. Но давайте подумаем, насколько эта реализация подойдет для реальных приложений.

Если мы работаем с реальным приложением, то после клика на кнопку тест будет ждать, пока запрос не вернет какой-то ответ с сервера. Если интернет будет медленным, или на сервере будут наблюдаться какие-то проблемы, то и время ожидания ответа может сильно увеличиться, соответственно будет увеличено время выполнения теста. При этом обратите внимание, что тест будет выполнен для каждой локали, которую мы передали в качестве параметра конструктора `DocLocScreenshotTestCase`, и каждый из этих тестов будет зависеть от скорости интернет-соединения и от работоспособности сервера.
1. Состояние прогресса зависит от скорости интернет-соединения и от работоспособности сервера. Если ответ вернется очень быстро, то состояние прогресса мы никогда не получим, и наш тест завершится неудачно.

Также сервер может вернуть ошибку, когда мы ее не ожидали, в этом случае тест завершится неудачно.
2. Для получения состояния ошибки мы отключаем интернет на устройстве, но в реальных приложениях часто бывает ситуация, когда в зависимости от типа ошибки поведение приложения должно отличаться. Например, если на устройстве нет интернета, то нужно показать сообщение пользователю, чтобы он включил интернет, а если сервер вернул какую-то ошибку, то отобразить соответствующий диалог. В этом случае сымитировать состояние ошибки в приложении становится очень сложной задачей.

На определенном этапе теста мы хотим сделать скриншот состояния ошибки. В данном случае мы одинаково реагируем на любой тип ошибки, показывая строчку «Что-то пошло не так», но часто бывают случаи, когда пользователю нужно сообщать о том, что конкретно произошло. Например, при отсутствии интернета, показать уведомление об этом, при ошибке на сервере показать соответствующий диалог и так далее. Поэтому в каких-то случаях для воспроизведения стейта с ошибкой будет достаточно отключить интернет на устройстве, а в каких-то это может стать проблемой, которую не так просто решить.
3. Цель «скриншотилки» - сделать снимки всех возможных состояний экрана, а не проверить работоспособность приложения. Тем не менее, если в момент проведения теста будут какие-то проблемы с интернетом, или сервер не будет отвечать на запросы, то при такой реализации тест завершится неудачно, и никаких снимков мы не получим.

Так мы приходим к следующему выводу: получить все необходимые стейты, имитируя действия пользователя, для скриншот-тестов нецелесообразно.

Во-первых, это может сильно замедлить выполнение теста.
Во-первых, некоторые состояние экрана получить очень сложно или даже невозможно.

Во-вторых, такие тесты начинают зависеть от многих факторов, таких как скорость интернета и работоспособность сервера, следовательно вероятность того, что эти тесты завершатся неудачно, возрастает.

В-третьих, некоторые состояния экрана получить очень сложно, и этот процесс может занять длительное время

## Взаимодействие View и ViewModel

Expand Down Expand Up @@ -474,6 +478,8 @@ class LoadUserScreenshots : DocLocScreenshotTestCase(locales = "en, fr") {
androidTestImplementation("io.mockk:mockk-android:1.13.3")
```

<img src="../images/screenshot_tests_2/gradle2.png" alt="Gradle"/>

!!! info
Если после синхронизации и запуска проекта у вас возникают ошибки, следуйте инструкциям в журнале ошибок. В случае, если разобраться не получилось, переключитесь на ветку `TECH-tutorial-results` и сверьте файл `build.gradle` из этой ветки с вашим

Expand Down Expand Up @@ -770,6 +776,8 @@ class LoadUserScreenshots : DocLocScreenshotTestCase(locales = "en, fr") {

Если мы тестируем фрагменты, то запускать активити, в которой этот фрагмент лежит, не нужно. Мы можем напрямую тестировать фрагменты. Для того чтобы у нас была такая возможность, необходимо добавить следующие зависимости в build.gradle

<img src="../images/screenshot_tests_2/gradle.png" alt="Gradle"/>

```kotlin
debugImplementation("androidx.fragment:fragment-testing-manifest:1.6.0"){
isTransitive = false
Expand Down Expand Up @@ -833,7 +841,7 @@ class LoadUserScreenshots : DocLocScreenshotTestCase(locales = "en, fr") {

## Меняем стиль

Вы могли обратить внимание, что внешний вид экрана в приложении отличается от того, который мы получили в результате выполнения теста. Проблема заключается в использовании стилей. Во время теста под капотом создается активити, которая является контейнером для нашего фрагмента. Стиль этой активити может отличаться от того, который используется у нас в приложении.
Вы могли обратить внимание, что внешний вид экрана в приложении отличается от того, который мы получили в результате выполнения теста. Проблема заключается в использовании [стилей]( https://developer.android.com/develop/ui/views/theming/themes). Во время теста под капотом создается активити, которая является контейнером для нашего фрагмента. Стиль этой активити может отличаться от того, который используется у нас в приложении.

Данная проблема решается очень просто – в качестве параметра в метод `launchFragmentInContainer` можно передать стиль, который должен использоваться внутри фрагмента, его можно найти в манифесте приложения

Expand Down Expand Up @@ -889,3 +897,4 @@ class LoadUserScreenshots : DocLocScreenshotTestCase(locales = "en, fr") {
## Итог

Это был очень насыщенный урок, в котором мы научились правильно устанавливать стейты во вьюмодель, тестировать фрагменты, использовать бибилотеку Mockk для мокирования сущностей, а также дорабатывать код приложения, чтобы его можно было покрыть screenshot-тестами.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
84 changes: 1 addition & 83 deletions docs/index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ And many more!

<img src="kaspresso.png" alt="Kaspresso"/>

<details>
<summary>

## Integration
</summary>

To integrate Kaspresso into your project:
1. If the `mavenCentral` repository does not exist, include it to your root `build.gradle` file:
Expand Down Expand Up @@ -79,25 +75,16 @@ dependencies {
}
```

</details>

## FAQ
For all questions you can reach out to us on [Discord](https://kas.pr/gh_discord).

## Tutorial *NEW*
To make it easier to learn the framework, a step-by-step tutorial is available on [our website](https://kasperskylab.github.io/Kaspresso/Tutorial/).

<details>
<summary>

## Capabilities of Kaspresso
</summary>

<details>
<summary>

### Readability
</summary>

We like the syntax that [Kakao](https://github.com/KakaoCup/Kakao) applies to write UI tests. This wrapper over Espresso uses the Kotlin DSL approach, that makes the code
significantly shorter and more readable. See the difference:

Expand Down Expand Up @@ -204,39 +191,21 @@ fun shouldPassOnNoInternetScanTest() =
}
```

</details>

<details>
<summary>

### Stability
</summary>

Sometimes your UI test passes ten times, then breaks on the eleventh attempt for some mysterious reason. It’s called *flakiness*.

The most popular reason for flakiness is the instability of the UI tests libraries, such as Espresso and UI Automator. To eliminate this instability, Kaspresso uses DSL wrappers and [interceptors](#Interceptors).

</details>

<details>
<summary>

### UI test libraries acceleration
</summary>

Let’s watch some short video that shows the difference between the original UI Automator (on the right) and the accelerated one (on the left).

![](https://habrastorage.org/webt/ti/kv/ki/tikvkij1vjesnacrxqm-lk0coly.gif)

Here is [a short explanation](https://kasperskylab.github.io/Kaspresso/Wiki/Kautomator-wrapper_over_UI_Automator/#accelerate-ui-automator) of why it is possible.

</details>

<details>
<summary>

### Interceptors
</summary>

We developed [Kaspresso behavior interceptors](https://kasperskylab.github.io/Kaspresso/Wiki/Kaspresso_configuration/#some-words-about-behavior-interceptors) on the base of [Kakao/Kautomator
Interceptors](https://kasperskylab.github.io/Kaspresso/Wiki/Kaspresso_configuration/#kaspresso-interceptors-based-on-kakaokautomator-interceptors) to catch failures.
Expand All @@ -248,36 +217,18 @@ Thanks to interceptors, you can do a lot of useful things, such as:

and many more (see [the manual](https://kasperskylab.github.io/Kaspresso/Wiki/Kaspresso_configuration/#kaspresso-interceptors-based-on-kakaokautomator-interceptors)).

</details>

<details>
<summary>

### Writing readable logs
</summary>

Kaspresso writes its own logs, detailed and readable:

<img src="https://habrastorage.org/webt/03/nn/qg/03nnqgupdqnwa_i4jwyz1uqq6r0.png" />
<img src="https://habrastorage.org/webt/tq/az/3v/tqaz3vjsgpw0-ivylrfbnuqyiqa.png" />

</details>

<details>
<summary>

### Ability to call ADB commands
</summary>

Espresso and UI Automator don't allow to call ADB commands from inside a test. To fix this problem, we developed AdbServer (see the [wiki](https://kasperskylab.github.io/Kaspresso/Wiki/Executing_adb_commands/)).

</details>

<details>
<summary>

### Ability to work with Android System
</summary>

You can use Kaspresso classes to work with Android System.

Expand All @@ -296,66 +247,33 @@ For example, with the ```Device``` class you can:

(see more about the [Device class](https://kasperskylab.github.io/Kaspresso/Wiki/Working_with_Android_OS/)).

</details>

<details>
<summary>

### Features screenshotting
</summary>

If you develop an application that is available across the world, you have to *localize* it into different languages. When UI is localized, it’s important for the translator to see the context of a word or a phrase, that is the specific screen.

With Kaspresso, translators can automatically take a screenshot of any screen. It’s incredibly fast, even for legacy screens, and you don't have to refactor or mock anything (see [the manual](https://kasperskylab.github.io/Kaspresso/Wiki/Screenshot_tests/)).

</details>

<details>
<summary>

### Configurability
</summary>

You can tune any part of Kaspresso (read [more](https://kasperskylab.github.io/Kaspresso/Wiki/Kaspresso_configuration/)).

</details>

<details>
<summary>

### Robolectric support
</summary>

You can run your UI-tests on the JVM environment. Additionally, almost all interceptors improving stability, readability and other will work.
Read [more](https://kasperskylab.github.io/Kaspresso/Wiki/Kaspresso_Robolectric/).

</details>

<details>
<summary>

### Allure support
</summary>

Kaspresso can generate very detailed Allure-reports for each test:
![](https://habrastorage.org/webt/tq/t7/ch/tqt7chcdczrgduhoukqhx1ertfc.png)
More information is available [here](https://kasperskylab.github.io/Kaspresso/Wiki/Kaspresso_Allure/).

</details>

<details>
<summary>

### Jetpack Compose support
</summary>

Now, you can write your Kaspresso tests for Jetpack Compose screens! DSL and all principles are the same.
So, you will not see any difference between tests for View screens and for Compose screens.
More information is available [here](https://kasperskylab.github.io/Kaspresso/Wiki/Jetpack_Compose/).

</details>
</details>

## Samples
All samples are available in the [samples](https://github.com/KasperskyLab/Kaspresso/tree/master/samples) folder.

Expand Down
Loading
Loading