Скриншот тесты
Основная цель
Иногда при разработке новых функций возникает необходимость проверить, корректно ли работает приложение на всех поддерживаемых языках. Ручное изменение настроек локали может занять много времени и потребовать усилий разработчиков, QA-инженеров и т. д. Кроме того, это может увеличить продолжительность процесса локализации.
Чтобы избежать этого, Kaspresso предоставляет класс DocLocScreenshotTestCase
, что позволяет делать скриншоты во всех указанных вами локалях. DocLocScreenshotTestCase
расширяется класс TestCase
и предлагает возможность делать скриншоты из коробки, вызывая метод DocLocScreenshotTestCase#captureScreenshot(String)
.
Использование
Чтобы создать скриншот тест, вы должны расширить класс DocLocScreenshotTestCase
, как показано ниже:
@RunWith(AndroidJUnit4::class)
class ScreenshotSampleTest : DocLocScreenshotTestCase(
locales = "en,ru"
) {
@ScreenShooterTest
@Test
fun test() {
before{
}.after {
}.run {
step("1. Do the first step") {
// ...
captureScreenshot("First step")
}
step("2. Do the second step") {
// ...
captureScreenshot("Second step")
}
}
}
}
В базовый конструктор передается один параметр: locales
- строка с разделенными запятыми локалями для запуска теста. Сделанные скриншоты будут доступны в памяти устройства по пути /sdcard/documents/screenshots/
.
Полный пример см. в ScreenshotSampleTest.
Обратите внимание, что тест помечен аннотацией @ScreenShooterTest
. Эта аннотация предназначена для фильтрации скриншот тестов от всех остальных для запуска. Например, вы можете передать эту аннотацию стандартному AndroidJUnitRunner
при помощи команды:
adb shell am instrument -w -e annotation com.kaspersky.kaspresso.annotations.ScreenShooterTest your.package.name/android.support.test.runner.AndroidJUnitRunner
Расположение файлов скриншотов
Все файлы снимков экрана хранятся по умолчанию в каталоге screenshots
.
Они отсортированы по локали и названию теста:
<base directory>/<test class canonical name>/<locale>/<your tag>.png
Для тестового кейса из примера дерево файлов должно выглядеть так:
- screenshots
- com.kaspersky.kaspressample.tests.docloc.ScreenshotSampleTest
- en
// файлы скриншотов
- ru
// файлы скриншотов
Итак, для сохранения скриншотов на внешнее хранилище тестовому приложению требуется разрешение android.permission.WRITE_EXTERNAL_STORAGE
.
Дополнительная метаинформация скриншота
Когда разработчик вызывает метод captureScreenshot("la-la-la")
, Kaspresso создает не только снимок экрана, но и специальный xml-файл. Этот xml-файл содержит данные обо всех элементах пользовательского интерфейса с их идентификаторами, расположенными на экране. Пример:
<Metadata>
<Window Left="0" Top="0" Width="1440" Height="2560">
<LocalizedString Text="Simple Fragment" LocValueDescription="com.kaspersky.kaspressample.test:id/text_view_title" Top="140" Left="307" Width="825" Height="146"/>
<LocalizedString Text="Button 1" LocValueDescription="com.kaspersky.kaspressample.test:id/button_1" Top="370" Left="84" Width="1272" Height="168"/>
<LocalizedString Text="Button 2" LocValueDescription="com.kaspersky.kaspressample.test:id/button_2" Top="622" Left="84" Width="1272" Height="168"/>
<LocalizedString Text="Kaspresso" LocValueDescription="com.kaspersky.kaspressample.test:id/edit" Top="874" Left="84" Width="1272" Height="158"/>
<LocalizedString Text="Simple screen" LocValueDescription="com.kaspersky.kaspressample.test:id/[id:ffffffff]" Top="51" Left="56" Width="446" Height="93"/>
</Window>
</Metadata>
Скриншоты системных диалогов/окон
Иногда вам нужно сделать скриншоты системных диалогов или окон. Вот почему вы должны изменить язык для всей системы. Для этого в конструкторе DocLocScreenshotTestCase
есть дополнительный параметр - changeSystemLocale
. Обратите внимание на то, что changeSystemLocale
, определенный в true, требует системного разрешения Manifest.permission.CHANGE_CONFIGURATION
.
Взгляните на код ниже:
@RunWith(AndroidJUnit4::class)
class ChangeSysLanguageTestCase : DocLocScreenshotTestCase(
screenshotsDirectory = File("screenshots"),
locales = "en,ru",
changeSystemLocale = true
) {
@ScreenShooterTest
@Test
fun test() {
before{
}.after {
}.run {
step("1. Do the first step") {
// ...
captureScreenshot("First step")
}
step("2. Do the second step") {
// ...
captureScreenshot("Second step")
}
}
}
}
Расширенное использование
В большинстве случаев нет необходимости запускать какую-то Activity, делать много шагов, прежде чем добраться до необходимого функционала. Часто показа фрагментов будет достаточно, чтобы сделать нужные скриншоты. Кроме того, когда вы используете архитектурный шаблон Model-View-Presenter, вы можете управлять состоянием пользовательского интерфейса непосредственно через интерфейс View. Таким образом, нет необходимости взаимодействовать с интерфейсом приложения и ждать изменений.
Сначала создайте базовую тестовую Activity с методом setFragment(Fragment)
в вашем приложении:
class FragmentTestActivity : AppCompatActivity() {
fun setFragment(fragment: Fragment) = with(supportFragmentManager.beginTransaction()) {
replace(android.R.id.content, fragment)
commit()
}
}
Затем добавьте тестовый пример скриншота базового продукта:
```kotlin open class ProductDocLocScreenshotTestCase : DocLocScreenshotTestCase( locales = "en,ru" ) {
@get:Rule
val activityTestRule = ActivityTestRule(FragmentTestActivity::class.java, false, true)
protected val activity: FragmentTestActivity
get() = activityTestRule.activity
}
Этот тестовый пример будет запускать вашу `FragmentTestActivity` при запуске. Теперь вы можете писать тесты для скриншотов.
Например, создайте новый тестовый класс, который расширяет `ProductDocLocScreenshotTestCase`:
```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")
}
// ... другие шаги
}
}
}
Как вы могли заметить, метод getUiSafeProxy
вызывается для получения экземпляра FeatureView
.
Этот метод обертывает ваш интерфейс View и возвращает на него прокси.
Прокси гарантирует, что все методы интерфейса View
, которые вы вызвали, будут вызываться в основном потоке.
Существует также getUiSafeProxyFromImplementation
, который оборачивает реализацию, а не интерфейс.
Полный пример см. в классе AdvancedScreenshotSampleTest.
Изменение пути и имени скриншотов
По умолчанию все скриншоты хранятся по адресу:
/sdcard/documents/screenshots/<locale>/<full qualified test class name>/<method name>.
Вы можете изменить это поведение, предоставив свою реализацию интерфейсов
ResourcesRootDirsProvider,
ResourcesDirsProvider,
ResourceFileNamesProvider и ResourcesDirNameProvider.
Узнайте подробности здесь.
Изменения
Мы были вынуждены изменить нашу систему предоставления ресурсов для поддержки Allure.
Изменения затронули основной конструктор DocLocScreenshotTestCase.
Но мы сохранили старый вариант использования DocLocScreenshotTestCase
со старой системой предоставления ресурсов в качестве вторичного конструктора.
Вы можете просмотреть вторичный конструктор как пример миграции со старой системы на новую.
Кроме того, мы сохранили тесты с использованием старой системы предоставления ресурсов в примерах, чтобы убедиться, что ничего не сломано.