SlideShare a Scribd company logo
1 of 30
Черемушкин Дмитрий
инженер
по автоматизации тестирования ПО
Scalable eCommerce Platform Solutions
Обо мнеОбо мне
6+ лет в тестировании ПО
ручное | автоматизированное
настольное | веб | мобильное
автоматизация рутинных
действий в QA-процессах,
интеграция инструментов
Черемушкин Дмитрий
1
2
Постановка задачиПостановка задачи
Имеется: фреймворк,
основанный на стеке технологий:
+ автоматизированные тесты для eCommerce веб-сайта
~ 2000 тесткейсов • Firefox, Chrome, IE • локальный и удаленный запуск
3
1 Запустить имеющиеся тесты
(в Android Browser и Mobile Safari)
Разработать новые тесты
(мобильная версия сайта + Android-приложение)
2
Необходимо:
на мобильных ОС Android и iOS
Постановка задачиПостановка задачи
4
Этапы решения задачиЭтапы решения задачи
11
устранение
проблем
+
завершение
интеграции
в фреймворк
создание
proof of
concept
+
выявление
проблем
выбор
инструмента
тестирования
на мобильных
платформах
22 33
5
Выбор инструментаВыбор инструмента
Требования:
open-source решение;
поддержка Java и WebDriver API;
поддержка ОС Android и iOS;
автоматизация приложений и браузеров;
работа на эмуляторах и физических устройствах;
активное развитие, наличие документации
6
Выбор инструментаВыбор инструмента
7
Выбор инструментаВыбор инструмента
iOS Android Java
WebDriver
API
Эмуля-
торы
Устройства
Keep It
Functional ✓ ✗ ✗
ObjectiveC
✗ ✓ ✗
Frank ✓ ✗
✗
Ruby +
Cucumber
✗ ✓ ✗
Instruments
(Apple)
✓ ✗ ✗
JavaScript
✗ ✓ ✓
MonkeyTalk ✓ ✓
✗
свой язык +
JavaScript
✗ ✓ ✓
uiautomator
(Google)
✗ ✓ ✓ ✗ ✓ ✓
8
Выбор инструментаВыбор инструмента
iOS Android Java
WebDriver
API
Эмуля-
торы
Устройства
Robotium ✓ ✓ ✓ ✗ ✓ ✓
Calabash ✓ ✓ ~
Cucumber;
Ruby gems
✗ ✓ ✓
AndroidDriver
(Selenium)
✗ ~
только
браузер
✓ ✓ ✓ ✓
Selendroid ✗ ✓ ✓ ✓ ✓ ✓
ios–driver ✓ ✗ ✓ ✓ ✓ ~
только
приложения
Appium ✓ ✓ ✓ ✓ ✓ ✓
9
Выбор инструментаВыбор инструмента
браузеры &
приложения
браузеры &
приложения
10
Appium: преимуществаAppium: преимущества
лёгкость внесения модификаций в серверную часть
работает без «агентов» в приложении
большой спектр поддерживаемых языков
распределённый запуск тестов (SeleniumGrid)
кросс-платформенность тестов
11
Appium: архитектураAppium: архитектура
Appium–
сервер
Тестовый
сценарий
WebDriver
JSON
Wire
Инструмент
автоматизации
Прило-
жение
uiautomator
& selendroid
instruments
API
автома-
тизации
низко-
уровневые
команды
12
Proof of concept: первый запускProof of concept: первый запуск
Вручную: вернуть исходное состояние системы
Вручную: посмотреть Appium-логи
report
stories
mvn clean test
Вручную: запустить Appium
Вручную: Узнать UDID (для iOS-устройств)
13
Appium: общие проблемыAppium: общие проблемы
✗
в гибридных приложениях
нужно переключаться между native и webview частями
✗
между тест-кейсами
cookies браузера не очищаются
✗ Android: js-метод `click()` не работает
✗ iOS: не снимаются скриншоты
✗ нет отката к “чистому” состоянию
14
Appium: проблемы интеграцииAppium: проблемы интеграции
✗ Maven не запускает Appium автоматически
✗ разные “логи” у Maven и Appium
✗ iOS–устройства: нужно указывать UDID при запуске
✗ Android: Appium не запускает GenyMotion–эмулятор
15
Примеры решений:Примеры решений:
запуск Appiumзапуск Appium
<profile>
<id>mobile_unix</id>
<activation>
<property><name>mobile</name></property>
<os><family>!windows</family></os>
</activation>
<build>
<plugins>
...
<profile>
<id>mobile_unix</id>
<activation>
<property><name>mobile</name></property>
<os><family>!windows</family></os>
</activation>
<build>
<plugins>
...
нет Appium-плагина для Maven✗
16
Примеры решений:Примеры решений:
запуск Appiumзапуск Appium
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions><execution>
<id>init</id>
<phase>validate</phase>
<goals><goal>exec</goal></goals>
<configuration>
<executable>sh</executable>
<environmentVariables>
<platform>${mobile}</platform>
<isDevice>${device}</isDevice>
</environmentVariables>
<commandlineArgs>-c 'source ./main.sh; launch_appium'</commandlineArgs>
</configuration>
</execution></executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions><execution>
<id>init</id>
<phase>validate</phase>
<goals><goal>exec</goal></goals>
<configuration>
<executable>sh</executable>
<environmentVariables>
<platform>${mobile}</platform>
<isDevice>${device}</isDevice>
</environmentVariables>
<commandlineArgs>-c 'source ./main.sh; launch_appium'</commandlineArgs>
</configuration>
</execution></executions>
</plugin>
17
Примеры решений:
гибридные приложения
public class ShopScreen extends CommonMobileScreen {
private ElementLocator txtScreenTitle = new ElementLocator
("Screen Title", "NATIVE_APP", By.xpath("//*[@id='title']");
public ShopScreen(WebDriverProvider driverProvider) {
super(driverProvider);
addElements(new MobileElement[]{txtScreenTitle, lnkShopCategory});
}
}
public class ShopScreen extends CommonMobileScreen {
private ElementLocator txtScreenTitle = new ElementLocator
("Screen Title", "NATIVE_APP", By.xpath("//*[@id='title']");
public ShopScreen(WebDriverProvider driverProvider) {
super(driverProvider);
addElements(new MobileElement[]{txtScreenTitle, lnkShopCategory});
}
}
private MobileElement txtScreenTitle =
new MobileElement ("Screen Title | xpath=//*[@id='title'] | NATIVE_APP");
private MobileElement lnkShopCategory =
new MobileElement ("Category link | xpath=//div[text()='%s'] | WEBVIEW");
Native и Webview элементы – в разных фреймах✗
18
Примеры решений:Примеры решений:
гибридные приложениягибридные приложения
public class CommonMobileMethods extends WebDriverPage {
private List<ElementLocator> elements = new ArrayList<ElementLocator>();
public ElementLocator getElementLocatorByName(String name) {
for (MobileElement element : getElements()) {
if (element.getName().equals(name)) {
this.switchTo().window(element.getType());
return element;
}
}
fail("[ERROR] Element '" + name + "' is not defined on '"
+ MobileScreens.getCurrentScreen() + '" screen.");
return;
}
}
public class CommonMobileMethods extends WebDriverPage {
private List<ElementLocator> elements = new ArrayList<ElementLocator>();
public ElementLocator getElementLocatorByName(String name) {
for (MobileElement element : getElements()) {
if (element.getName().equals(name)) {
this.switchTo().window(element.getType());
return element;
}
}
fail("[ERROR] Element '" + name + "' is not defined on '"
+ MobileScreens.getCurrentScreen() + '" screen.");
return;
}
}
this.switchTo().window(element.getType());
public MobileElement getElementLocatorByName(String name) {
19
Примеры решений:Примеры решений:
замена javascript `click()` на Androidзамена javascript `click()` на Android
public class CommonMethods extends WebDriverPage {
public void jsClickElementByLoc(By loc) {
if (isLocatorPresentOnPage(loc)) {
WebElement element = findElement(loc);
if (isBrowser("android")) {
new TouchActions(getdriver()).singleTap(element).perform();
} else {
JavascriptExecutor js = (JavascriptExecutor) getDriver();
js.executeScript("arguments[0].click()", element);
}
}
}
public class CommonMethods extends WebDriverPage {
public void jsClickElementByLoc(By loc) {
if (isLocatorPresentOnPage(loc)) {
WebElement element = findElement(loc);
if (isBrowser("android")) {
new TouchActions(getdriver()).singleTap(element).perform();
} else {
JavascriptExecutor js = (JavascriptExecutor) getDriver();
js.executeScript("arguments[0].click()", element);
}
}
}
if (isBrowser("android")) {
new TouchActions(getdriver()).singleTap(element).perform();
Android: JavaScript-клик не работает✗
20
Примеры решений:Примеры решений:
снимки экрана на iOSснимки экрана на iOS
static class ScreenshootingRemoteWebDriver extends RemoteWebDriver
implements TakesScreenshot {
private static final String IOS_SCREENSHOT_CMD = "mobile :getScreenshot”;
public <X> X getScreenshotAs(OutputType<X> target)
throws WebDriverException {
String base64 = "";
if (isBrowser("ios")) {
base64 = execute(IOS_SCREENSHOT_CMD).getValue().toString();
} else {
base64 = execute(DriverCommand.SCREENSHOT).getValue().toString();
}
return target.convertFromBase64Png(base64);
}
static class ScreenshootingRemoteWebDriver extends RemoteWebDriver
implements TakesScreenshot {
private static final String IOS_SCREENSHOT_CMD = "mobile :getScreenshot”;
public <X> X getScreenshotAs(OutputType<X> target)
throws WebDriverException {
String base64 = "";
if (isBrowser("ios")) {
base64 = execute(IOS_SCREENSHOT_CMD).getValue().toString();
} else {
base64 = execute(DriverCommand.SCREENSHOT).getValue().toString();
}
return target.convertFromBase64Png(base64);
}
if (isBrowser("ios")) {
base64 = execute(IOS_SCREENSHOT_CMD).getValue().toString();
} else {
base64 = execute(DriverCommand.SCREENSHOT).getValue().toString();
}
private static final String IOS_SCREENSHOT_CMD = "mobile :getScreenshot”;
iOS: стандартная функция не снимает скриншоты✗
21
Примеры решений:Примеры решений:
удаление приложенийудаление приложений
public class BaseStoriesRunner extends JUnitStories {
protected static final String PROPERTY_MOBILE = "mobile”;
@Test
public void run() throws Throwable {
try {
beforeRun();
getEmbedder().runStoriesAsPaths(storyPath);
} finally {
afterRun();
}
}
protected void afterRun() {
if (StringUtils.isNotBlank(System.getProperty(PROPERTY_MOBILE))) {
uninstallMobileApps();
}
}
}
public class BaseStoriesRunner extends JUnitStories {
protected static final String PROPERTY_MOBILE = "mobile”;
@Test
public void run() throws Throwable {
try {
beforeRun();
getEmbedder().runStoriesAsPaths(storyPath);
} finally {
afterRun();
}
}
protected void afterRun() {
if (StringUtils.isNotBlank(System.getProperty(PROPERTY_MOBILE))) {
uninstallMobileApps();
}
}
}
protected void afterRun() {
if (StringUtils.isNotBlank(System.getProperty(PROPERTY_MOBILE))) {
uninstallMobileApps();
}
}
afterRun();
Нет отката к исходному состоянию✗
22
Примеры решений:Примеры решений:
удаление приложенийудаление приложений
public class MobileUtils {
public static void uninstallMobileApps() {
executeShCommand(UNINSTALL_APPS_COMMAND);
}
private static void RunCommand(String command) {
try {
String line;
Process p = new ProcessBuilder(command).start();
BufferedReader input = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
}
input.close();
} catch (Exception err) { err.printStackTrace(); }
}
}
public class MobileUtils {
public static void uninstallMobileApps() {
executeShCommand(UNINSTALL_APPS_COMMAND);
}
private static void RunCommand(String command) {
try {
String line;
Process p = new ProcessBuilder(command).start();
BufferedReader input = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
}
input.close();
} catch (Exception err) { err.printStackTrace(); }
}
}
public static void uninstallMobileApps() {
if isBrowser("ios") { RunCommand(IOS_UNINSTALL_APPS); }
if isBrowser("android") { RunCommand(IOS_UNINSTALL_APPS_COMMAND); }
}
Process p = new ProcessBuilder(command).start();
23
Примеры решений:Примеры решений:
удаление приложенийудаление приложений
public class MobileUtils {
private final String SEPARATOR = "; ";
private final String PROPERTY_ANDROID_APP_PACKAGE = "android.appPackage";
private final String PROPERTY_IOS_APP_BUNDLE = "ios.appBundle";
private final String ANDROID_SELENDROID_PACKAGE = "io.selendroid";
private final String ANDROID_BROWSER_PACKAGE = "io.selendroid.androiddriver";
private final String ANDROID_UNLOCK_PACKAGE = "io.appium.unlock";
private final String IOS_SAFARILAUNCHER_BUNDLE =
"com.bytearc.SafariLauncher";
private final String UNINSTALL_APPS_COMMAND =
ADB_PATH +" uninstall "+ System.getProperty(ANDROID_APP_PACKAGE) + QUIET +
ADB_PATH +" uninstall "+ ANDROID_BROWSER_PACKAGE + QUIET +
ADB_PATH +" uninstall "+ ANDROID_SELENDROID_PACKAGE + QUIET +
ADB_PATH +" uninstall "+ ANDROID_UNLOCK_PACKAGE + QUIET +
FRUITSTRAP_PATH +" uninstall --bundle "+ System.getProperty(IOS_APP_BUNDLE)
+ QUIET
+
}
public class MobileUtils {
private final String SEPARATOR = "; ";
private final String PROPERTY_ANDROID_APP_PACKAGE = "android.appPackage";
private final String PROPERTY_IOS_APP_BUNDLE = "ios.appBundle";
private final String ANDROID_SELENDROID_PACKAGE = "io.selendroid";
private final String ANDROID_BROWSER_PACKAGE = "io.selendroid.androiddriver";
private final String ANDROID_UNLOCK_PACKAGE = "io.appium.unlock";
private final String IOS_SAFARILAUNCHER_BUNDLE =
"com.bytearc.SafariLauncher";
private final String UNINSTALL_APPS_COMMAND =
ADB_PATH +" uninstall "+ System.getProperty(ANDROID_APP_PACKAGE) + QUIET +
ADB_PATH +" uninstall "+ ANDROID_BROWSER_PACKAGE + QUIET +
ADB_PATH +" uninstall "+ ANDROID_SELENDROID_PACKAGE + QUIET +
ADB_PATH +" uninstall "+ ANDROID_UNLOCK_PACKAGE + QUIET +
FRUITSTRAP_PATH +" uninstall --bundle "+ System.getProperty(IOS_APP_BUNDLE)
+ QUIET
+
}
private final String ANDROID_UNINSTALL_APPS_COMMAND =
"adb uninstall " + System.getProperty(ANDROID_APP_PACKAGE) + SEPARATOR +
"adb uninstall " + ANDROID_BROWSER_PACKAGE + SEPARATOR +
"adb uninstall " + ANDROID_SELENDROID_PACKAGE + SEPARATOR +
"adb uninstall " + ANDROID_UNLOCK_PACKAGE;
private final String IOS_UNINSTALL_APPS_COMMAND =
"fruitstrap uninstall --bundle " + IOS_SAFARILAUNCHER_BUNDLE + SEPARATOR +
"fruitstrap uninstall --bundle " + System.getProperty(IOS_APP_BUNDLE);
24
Примеры решений:Примеры решений:
вывод Appium-ошибоквывод Appium-ошибок
public class CustomPerStoryWebDriverSteps extends PerStoryWebDriverSteps {
public static final String PROPERTY_MOBILE = "mobile";
@AfterScenario(uponOutcome = AfterScenario.Outcome.FAILURE)
public void afterScenarioFailure(UUIDExceptionWrapper uuidWrappedFailure){
if (uuidWrappedFailure instanceof PendingStepFound) {
return;
}
if (StringUtils.isNotBlank(System.getProperty(PROPERTY_MOBILE))) {
MobileUtils.outputAppiumErrors();
}
}
}
public class CustomPerStoryWebDriverSteps extends PerStoryWebDriverSteps {
public static final String PROPERTY_MOBILE = "mobile";
@AfterScenario(uponOutcome = AfterScenario.Outcome.FAILURE)
public void afterScenarioFailure(UUIDExceptionWrapper uuidWrappedFailure){
if (uuidWrappedFailure instanceof PendingStepFound) {
return;
}
if (StringUtils.isNotBlank(System.getProperty(PROPERTY_MOBILE))) {
MobileUtils.outputAppiumErrors();
}
}
}
if (StringUtils.isNotBlank(System.getProperty(PROPERTY_MOBILE))) {
MobileUtils.outputAppiumErrors();
}
@AfterScenario(uponOutcome = AfterScenario.Outcome.FAILURE)
Appium-ошибки не показываются в логе Maven’а✗
25
Примеры решений:Примеры решений:
вывод Appium-ошибоквывод Appium-ошибок
public class MobileUtils {
private final String APPIUM_LOG_PATH = "./target/mobile/appium.log";
private final String APPIUM_FULL_LOG_PATH =
"./target/mobile/appium_full.log";
private static final String OUTPUT_APPIUM_ERRORS =
"errors=$(grep 'error: |Error :|STDERR' "+ APPIUM_LOG_PATH +");" +
"[ -n $errors ] && echo $errors | sed s/^/'[ERROR] appium.log: '/gn" +
" && cat ”+ APPIUM_LOG_PATH +" >>"+ APPIUM_FULL_LOG_PATH +
" && echo '' >”+ APPIUM_LOG_PATH;
public static void outputAppiumErrors() {
executeShCommand(OUTPUT_APPIUM_ERRORS);
}
}
public class MobileUtils {
private final String APPIUM_LOG_PATH = "./target/mobile/appium.log";
private final String APPIUM_FULL_LOG_PATH =
"./target/mobile/appium_full.log";
private static final String OUTPUT_APPIUM_ERRORS =
"errors=$(grep 'error: |Error :|STDERR' "+ APPIUM_LOG_PATH +");" +
"[ -n $errors ] && echo $errors | sed s/^/'[ERROR] appium.log: '/gn" +
" && cat ”+ APPIUM_LOG_PATH +" >>"+ APPIUM_FULL_LOG_PATH +
" && echo '' >”+ APPIUM_LOG_PATH;
public static void outputAppiumErrors() {
executeShCommand(OUTPUT_APPIUM_ERRORS);
}
}
private static final String OUTPUT_APPIUM_ERRORS =
"errors=$(grep 'error: |Error :|STDERR' " + APPIUM_LOG_PATH + ");" +
"[ -n $errors ] && echo $errors | sed s/^/'[ERROR] appium.log: '/gn" +
" && cat " + APPIUM_LOG_PATH + " >>" + APPIUM_FULL_LOG_PATH +
" && echo '' >" + APPIUM_LOG_PATH;
public static void outputAppiumErrors() {
executeShCommand(OUTPUT_APPIUM_ERRORS);
}
26
откат к «чистому» cостоянию
при ошибке: Appium-лог + скриншот✗
Итоговый фреймворк:Итоговый фреймворк:
схема работысхема работы
очистка cookies
запуск тестов
запуск Appium сервера
[и эмулятора]
сборка
тестов
27
mobile = (?: android_browser | ios_safari | android_app | ios_app )
$ cat mobile.properties
ios.app = TestedApp.ipa
ios.simulatorType = iPhone (3.5 inch)
ios.version = 7.0
android.app = TestedApp.apk
android.waitActivity = com.app.MainActivity
android.vmType = GenyMotion
android.vmName = Nexus One - 4.2.2 - API 17 - 480x800
mobile = (?: android_browser | ios_safari | android_app | ios_app )
$ cat mobile.properties
ios.app = TestedApp.ipa
ios.simulatorType = iPhone (3.5 inch)
ios.version = 7.0
android.app = TestedApp.apk
android.waitActivity = com.app.MainActivity
android.vmType = GenyMotion
android.vmName = Nexus One - 4.2.2 - API 17 - 480x800
Итоговый фреймворк:Итоговый фреймворк:
параметры запускапараметры запуска
$ mvn clean test
-Dmobile=android_app -Ddevice=false –Dsuite=MobileTestSuite
$ mvn clean test
-Dmobile=android_app -Ddevice=false –Dsuite=MobileTestSuite
$ cat mobile.properties
28
ЗаключениеЗаключение
запуск существующих веб-тестов
в мобильных браузерах
разработка новых кросс-платформенных тестов
для мобильных сайтов и приложений
11
использование принятых на проекте практик
в мобильном тестировании
22
33
Возможности полученного решения:
29
Перспективы развитияПерспективы развития
расширение корпоративной инфраструктуры
SeleniumGrid нодами для мобильного тестирования
реализация решения в виде Maven-плагина
для интеграции в другие проекты
добавление возможности мобильного тестирования
на ОС Windows Phone и Windows 8
увеличение количества мобильных браузеров,
поддерживаемых фреймворком
Scalable eCommerce Platform SolutionsScalable eCommerce Platform Solutions
Dmitry.Cheremushkin@gmail.com
DCheremushkin@griddynamics.com

More Related Content

What's hot

iOS and Android Mobile Test Automation
iOS and Android Mobile Test AutomationiOS and Android Mobile Test Automation
iOS and Android Mobile Test AutomationAndrii Dzynia
 
Тестируем мобильные приложения в облаках с appium
Тестируем мобильные приложения в облаках с appiumТестируем мобильные приложения в облаках с appium
Тестируем мобильные приложения в облаках с appiumSQALab
 
Monkey Talk - кросс-платформенное средство автоматизации тестирования мобильн...
Monkey Talk - кросс-платформенное средство автоматизации тестирования мобильн...Monkey Talk - кросс-платформенное средство автоматизации тестирования мобильн...
Monkey Talk - кросс-платформенное средство автоматизации тестирования мобильн...SQALab
 
Способы оптимизации ручного тестирования веб-сайтов в мобильных браузерах
Способы оптимизации ручного тестирования веб-сайтов в мобильных браузерахСпособы оптимизации ручного тестирования веб-сайтов в мобильных браузерах
Способы оптимизации ручного тестирования веб-сайтов в мобильных браузерахSQALab
 
Степан Гончаров «Тестирование Android-приложений с помощью Robotium и Spoon»
Степан Гончаров «Тестирование Android-приложений с помощью Robotium и Spoon»Степан Гончаров «Тестирование Android-приложений с помощью Robotium и Spoon»
Степан Гончаров «Тестирование Android-приложений с помощью Robotium и Spoon»e-Legion
 
Эффективное тестирование сайта на мобильных устройствах
Эффективное тестирование сайта на мобильных устройствахЭффективное тестирование сайта на мобильных устройствах
Эффективное тестирование сайта на мобильных устройствахSQALab
 
Особенности тестирования мобильных приложений (Android, iOS)
Особенности тестирования мобильных приложений (Android, iOS)Особенности тестирования мобильных приложений (Android, iOS)
Особенности тестирования мобильных приложений (Android, iOS)Эльвина Сакаева
 
Подходы к тестированию андроид приложений
Подходы к тестированию андроид приложенийПодходы к тестированию андроид приложений
Подходы к тестированию андроид приложенийSQALab
 
Как сейчас тесты в Android пишут, Денис Неклюдов, Google Dev Expert, Москва
 Как сейчас тесты в Android пишут, Денис Неклюдов, Google Dev Expert, Москва  Как сейчас тесты в Android пишут, Денис Неклюдов, Google Dev Expert, Москва
Как сейчас тесты в Android пишут, Денис Неклюдов, Google Dev Expert, Москва it-people
 
До зеленых человечков: исследовательское тестирование мобильных приложений
До зеленых человечков: исследовательское тестирование мобильных приложенийДо зеленых человечков: исследовательское тестирование мобильных приложений
До зеленых человечков: исследовательское тестирование мобильных приложенийSQALab
 
Виртуализация и автоматизация тестирования мобильных приложений
Виртуализация и автоматизация тестирования мобильных приложенийВиртуализация и автоматизация тестирования мобильных приложений
Виртуализация и автоматизация тестирования мобильных приложенийSQALab
 
Мобильные браузеры: очевидное-невероятное
Мобильные браузеры: очевидное-невероятноеМобильные браузеры: очевидное-невероятное
Мобильные браузеры: очевидное-невероятноеSQALab
 
Тестирование мобильных приложений
Тестирование мобильных приложенийТестирование мобильных приложений
Тестирование мобильных приложенийAlexander Khozya
 
Поиск багов при тестировании переходов с веба в мобильное приложение
Поиск багов при тестировании переходов с веба в мобильное приложениеПоиск багов при тестировании переходов с веба в мобильное приложение
Поиск багов при тестировании переходов с веба в мобильное приложениеSQALab
 
Анализ инструментов автоматизации мобильного тестирования
Анализ инструментов автоматизации мобильного тестированияАнализ инструментов автоматизации мобильного тестирования
Анализ инструментов автоматизации мобильного тестированияSQALab
 
Антон Семенченко, Никита Беликов "Инструменты автоматизации тестирования моби...
Антон Семенченко, Никита Беликов "Инструменты автоматизации тестирования моби...Антон Семенченко, Никита Беликов "Инструменты автоматизации тестирования моби...
Антон Семенченко, Никита Беликов "Инструменты автоматизации тестирования моби...QA Club Minsk
 
Эльдар Гусейнов "Эффективная архитектура мобильной автоматизации для проектов...
Эльдар Гусейнов "Эффективная архитектура мобильной автоматизации для проектов...Эльдар Гусейнов "Эффективная архитектура мобильной автоматизации для проектов...
Эльдар Гусейнов "Эффективная архитектура мобильной автоматизации для проектов...QA Club Minsk
 
Тестирование PhoneGap-приложений: специфика + опыт
Тестирование PhoneGap-приложений: специфика + опытТестирование PhoneGap-приложений: специфика + опыт
Тестирование PhoneGap-приложений: специфика + опытSQALab
 
Тестирование iOS приложений. С чего начать?
Тестирование iOS приложений. С чего начать?Тестирование iOS приложений. С чего начать?
Тестирование iOS приложений. С чего начать?Natalia Savastiuk
 
Mobile testing: Android, iOS, BlackBerry
Mobile testing: Android, iOS, BlackBerryMobile testing: Android, iOS, BlackBerry
Mobile testing: Android, iOS, BlackBerryQA Club Kiev
 

What's hot (20)

iOS and Android Mobile Test Automation
iOS and Android Mobile Test AutomationiOS and Android Mobile Test Automation
iOS and Android Mobile Test Automation
 
Тестируем мобильные приложения в облаках с appium
Тестируем мобильные приложения в облаках с appiumТестируем мобильные приложения в облаках с appium
Тестируем мобильные приложения в облаках с appium
 
Monkey Talk - кросс-платформенное средство автоматизации тестирования мобильн...
Monkey Talk - кросс-платформенное средство автоматизации тестирования мобильн...Monkey Talk - кросс-платформенное средство автоматизации тестирования мобильн...
Monkey Talk - кросс-платформенное средство автоматизации тестирования мобильн...
 
Способы оптимизации ручного тестирования веб-сайтов в мобильных браузерах
Способы оптимизации ручного тестирования веб-сайтов в мобильных браузерахСпособы оптимизации ручного тестирования веб-сайтов в мобильных браузерах
Способы оптимизации ручного тестирования веб-сайтов в мобильных браузерах
 
Степан Гончаров «Тестирование Android-приложений с помощью Robotium и Spoon»
Степан Гончаров «Тестирование Android-приложений с помощью Robotium и Spoon»Степан Гончаров «Тестирование Android-приложений с помощью Robotium и Spoon»
Степан Гончаров «Тестирование Android-приложений с помощью Robotium и Spoon»
 
Эффективное тестирование сайта на мобильных устройствах
Эффективное тестирование сайта на мобильных устройствахЭффективное тестирование сайта на мобильных устройствах
Эффективное тестирование сайта на мобильных устройствах
 
Особенности тестирования мобильных приложений (Android, iOS)
Особенности тестирования мобильных приложений (Android, iOS)Особенности тестирования мобильных приложений (Android, iOS)
Особенности тестирования мобильных приложений (Android, iOS)
 
Подходы к тестированию андроид приложений
Подходы к тестированию андроид приложенийПодходы к тестированию андроид приложений
Подходы к тестированию андроид приложений
 
Как сейчас тесты в Android пишут, Денис Неклюдов, Google Dev Expert, Москва
 Как сейчас тесты в Android пишут, Денис Неклюдов, Google Dev Expert, Москва  Как сейчас тесты в Android пишут, Денис Неклюдов, Google Dev Expert, Москва
Как сейчас тесты в Android пишут, Денис Неклюдов, Google Dev Expert, Москва
 
До зеленых человечков: исследовательское тестирование мобильных приложений
До зеленых человечков: исследовательское тестирование мобильных приложенийДо зеленых человечков: исследовательское тестирование мобильных приложений
До зеленых человечков: исследовательское тестирование мобильных приложений
 
Виртуализация и автоматизация тестирования мобильных приложений
Виртуализация и автоматизация тестирования мобильных приложенийВиртуализация и автоматизация тестирования мобильных приложений
Виртуализация и автоматизация тестирования мобильных приложений
 
Мобильные браузеры: очевидное-невероятное
Мобильные браузеры: очевидное-невероятноеМобильные браузеры: очевидное-невероятное
Мобильные браузеры: очевидное-невероятное
 
Тестирование мобильных приложений
Тестирование мобильных приложенийТестирование мобильных приложений
Тестирование мобильных приложений
 
Поиск багов при тестировании переходов с веба в мобильное приложение
Поиск багов при тестировании переходов с веба в мобильное приложениеПоиск багов при тестировании переходов с веба в мобильное приложение
Поиск багов при тестировании переходов с веба в мобильное приложение
 
Анализ инструментов автоматизации мобильного тестирования
Анализ инструментов автоматизации мобильного тестированияАнализ инструментов автоматизации мобильного тестирования
Анализ инструментов автоматизации мобильного тестирования
 
Антон Семенченко, Никита Беликов "Инструменты автоматизации тестирования моби...
Антон Семенченко, Никита Беликов "Инструменты автоматизации тестирования моби...Антон Семенченко, Никита Беликов "Инструменты автоматизации тестирования моби...
Антон Семенченко, Никита Беликов "Инструменты автоматизации тестирования моби...
 
Эльдар Гусейнов "Эффективная архитектура мобильной автоматизации для проектов...
Эльдар Гусейнов "Эффективная архитектура мобильной автоматизации для проектов...Эльдар Гусейнов "Эффективная архитектура мобильной автоматизации для проектов...
Эльдар Гусейнов "Эффективная архитектура мобильной автоматизации для проектов...
 
Тестирование PhoneGap-приложений: специфика + опыт
Тестирование PhoneGap-приложений: специфика + опытТестирование PhoneGap-приложений: специфика + опыт
Тестирование PhoneGap-приложений: специфика + опыт
 
Тестирование iOS приложений. С чего начать?
Тестирование iOS приложений. С чего начать?Тестирование iOS приложений. С чего начать?
Тестирование iOS приложений. С чего начать?
 
Mobile testing: Android, iOS, BlackBerry
Mobile testing: Android, iOS, BlackBerryMobile testing: Android, iOS, BlackBerry
Mobile testing: Android, iOS, BlackBerry
 

Similar to Appium для народа

End-2-End UI автоматизация в мобильном приложении. Наша реализация
End-2-End UI автоматизация в мобильном приложении. Наша реализацияEnd-2-End UI автоматизация в мобильном приложении. Наша реализация
End-2-End UI автоматизация в мобильном приложении. Наша реализацияSQALab
 
Автоматизация UI тестирования под Windows и Windows Phone
Автоматизация UI тестирования под Windows и Windows PhoneАвтоматизация UI тестирования под Windows и Windows Phone
Автоматизация UI тестирования под Windows и Windows PhoneCodeFest
 
DevCon 2016 - Xamarin
DevCon 2016 - XamarinDevCon 2016 - Xamarin
DevCon 2016 - XamarinAnton Shunkov
 
"Гибридное приложение: полгода после релиза" Легчилин Андрей, Парадеев Роман,...
"Гибридное приложение: полгода после релиза" Легчилин Андрей, Парадеев Роман,..."Гибридное приложение: полгода после релиза" Легчилин Андрей, Парадеев Роман,...
"Гибридное приложение: полгода после релиза" Легчилин Андрей, Парадеев Роман,...it-people
 
Selenium 2.0: обзор новых возможностей
Selenium 2.0: обзор новых возможностейSelenium 2.0: обзор новых возможностей
Selenium 2.0: обзор новых возможностейPaul Stashevsky
 
Unity Android и Java. Демо сессия
Unity Android и Java. Демо сессияUnity Android и Java. Демо сессия
Unity Android и Java. Демо сессияDevGAMM Conference
 
E2E-тестирование мобильных приложений
E2E-тестирование мобильных приложенийE2E-тестирование мобильных приложений
E2E-тестирование мобильных приложенийMoscowJS
 
Автоматизация тестирования iOS приложений: от идеи к готовому решению
Автоматизация тестирования iOS приложений: от идеи к готовому решениюАвтоматизация тестирования iOS приложений: от идеи к готовому решению
Автоматизация тестирования iOS приложений: от идеи к готовому решениюSQALab
 
Solit 2014, Appium. Тестируем гибридные мобильные прирложения в стиле webdriv...
Solit 2014, Appium. Тестируем гибридные мобильные прирложения в стиле webdriv...Solit 2014, Appium. Тестируем гибридные мобильные прирложения в стиле webdriv...
Solit 2014, Appium. Тестируем гибридные мобильные прирложения в стиле webdriv...solit
 
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Ontico
 
Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов
 Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов
Зачем нужен JavaScript в iOS-приложениях. Евгений ДымовYandex
 
Android: Как создать свое первое приложение?
Android: Как создать свое первое приложение?Android: Как создать свое первое приложение?
Android: Как создать свое первое приложение?Kuban Dzhakipov
 
Антон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в androidАнтон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в androidDataArt
 
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...Andrey Rebrov
 
Плюсы и минусы автоматизации, пример из жизни
Плюсы и минусы автоматизации, пример из жизниПлюсы и минусы автоматизации, пример из жизни
Плюсы и минусы автоматизации, пример из жизниz-tech
 
Selenide puzzlers @ devclub.eu
Selenide puzzlers @ devclub.euSelenide puzzlers @ devclub.eu
Selenide puzzlers @ devclub.euAndrei Solntsev
 
(Seleniumcamp) Selenium RC for QA Engineer
(Seleniumcamp) Selenium RC for QA Engineer(Seleniumcamp) Selenium RC for QA Engineer
(Seleniumcamp) Selenium RC for QA EngineerYan Alexeenko
 
Droidcon Moscow 2015. Google Analytics и GTM для мобильных приложений Android...
Droidcon Moscow 2015. Google Analytics и GTM для мобильных приложений Android...Droidcon Moscow 2015. Google Analytics и GTM для мобильных приложений Android...
Droidcon Moscow 2015. Google Analytics и GTM для мобильных приложений Android...Mail.ru Group
 

Similar to Appium для народа (20)

End-2-End UI автоматизация в мобильном приложении. Наша реализация
End-2-End UI автоматизация в мобильном приложении. Наша реализацияEnd-2-End UI автоматизация в мобильном приложении. Наша реализация
End-2-End UI автоматизация в мобильном приложении. Наша реализация
 
Behavior Driven Development
Behavior Driven DevelopmentBehavior Driven Development
Behavior Driven Development
 
Автоматизация UI тестирования под Windows и Windows Phone
Автоматизация UI тестирования под Windows и Windows PhoneАвтоматизация UI тестирования под Windows и Windows Phone
Автоматизация UI тестирования под Windows и Windows Phone
 
DevCon 2016 - Xamarin
DevCon 2016 - XamarinDevCon 2016 - Xamarin
DevCon 2016 - Xamarin
 
"Гибридное приложение: полгода после релиза" Легчилин Андрей, Парадеев Роман,...
"Гибридное приложение: полгода после релиза" Легчилин Андрей, Парадеев Роман,..."Гибридное приложение: полгода после релиза" Легчилин Андрей, Парадеев Роман,...
"Гибридное приложение: полгода после релиза" Легчилин Андрей, Парадеев Роман,...
 
Selenium 2.0: обзор новых возможностей
Selenium 2.0: обзор новых возможностейSelenium 2.0: обзор новых возможностей
Selenium 2.0: обзор новых возможностей
 
Unity Android и Java. Демо сессия
Unity Android и Java. Демо сессияUnity Android и Java. Демо сессия
Unity Android и Java. Демо сессия
 
Automation testing desktop applications
Automation testing desktop applicationsAutomation testing desktop applications
Automation testing desktop applications
 
E2E-тестирование мобильных приложений
E2E-тестирование мобильных приложенийE2E-тестирование мобильных приложений
E2E-тестирование мобильных приложений
 
Автоматизация тестирования iOS приложений: от идеи к готовому решению
Автоматизация тестирования iOS приложений: от идеи к готовому решениюАвтоматизация тестирования iOS приложений: от идеи к готовому решению
Автоматизация тестирования iOS приложений: от идеи к готовому решению
 
Solit 2014, Appium. Тестируем гибридные мобильные прирложения в стиле webdriv...
Solit 2014, Appium. Тестируем гибридные мобильные прирложения в стиле webdriv...Solit 2014, Appium. Тестируем гибридные мобильные прирложения в стиле webdriv...
Solit 2014, Appium. Тестируем гибридные мобильные прирложения в стиле webdriv...
 
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
 
Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов
 Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов
Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов
 
Android: Как создать свое первое приложение?
Android: Как создать свое первое приложение?Android: Как создать свое первое приложение?
Android: Как создать свое первое приложение?
 
Антон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в androidАнтон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в android
 
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
 
Плюсы и минусы автоматизации, пример из жизни
Плюсы и минусы автоматизации, пример из жизниПлюсы и минусы автоматизации, пример из жизни
Плюсы и минусы автоматизации, пример из жизни
 
Selenide puzzlers @ devclub.eu
Selenide puzzlers @ devclub.euSelenide puzzlers @ devclub.eu
Selenide puzzlers @ devclub.eu
 
(Seleniumcamp) Selenium RC for QA Engineer
(Seleniumcamp) Selenium RC for QA Engineer(Seleniumcamp) Selenium RC for QA Engineer
(Seleniumcamp) Selenium RC for QA Engineer
 
Droidcon Moscow 2015. Google Analytics и GTM для мобильных приложений Android...
Droidcon Moscow 2015. Google Analytics и GTM для мобильных приложений Android...Droidcon Moscow 2015. Google Analytics и GTM для мобильных приложений Android...
Droidcon Moscow 2015. Google Analytics и GTM для мобильных приложений Android...
 

More from SQALab

Готовим стажировку
Готовим стажировкуГотовим стажировку
Готовим стажировкуSQALab
 
Куда приводят мечты? или Искусство развития тестировщика
Куда приводят мечты? или Искусство развития тестировщикаКуда приводят мечты? или Искусство развития тестировщика
Куда приводят мечты? или Искусство развития тестировщикаSQALab
 
Оптимизация Selenium тестов и ускорение их поддержки
Оптимизация Selenium тестов и ускорение их поддержкиОптимизация Selenium тестов и ускорение их поддержки
Оптимизация Selenium тестов и ускорение их поддержкиSQALab
 
Автоматизация 0.0: 0 - бюджет, 0 - опыт программирования
Автоматизация 0.0: 0 - бюджет, 0 - опыт программированияАвтоматизация 0.0: 0 - бюджет, 0 - опыт программирования
Автоматизация 0.0: 0 - бюджет, 0 - опыт программированияSQALab
 
Нагрузочное тестирование нестандартных протоколов с использованием Citrix и J...
Нагрузочное тестирование нестандартных протоколов с использованием Citrix и J...Нагрузочное тестирование нестандартных протоколов с использованием Citrix и J...
Нагрузочное тестирование нестандартных протоколов с использованием Citrix и J...SQALab
 
Continuous performance testing
Continuous performance testingContinuous performance testing
Continuous performance testingSQALab
 
Конфиги вместо костылей. Pytestconfig и зачем он нужен
Конфиги вместо костылей. Pytestconfig и зачем он нуженКонфиги вместо костылей. Pytestconfig и зачем он нужен
Конфиги вместо костылей. Pytestconfig и зачем он нуженSQALab
 
Команда чемпионов в ИТ стихии
Команда чемпионов в ИТ стихииКоманда чемпионов в ИТ стихии
Команда чемпионов в ИТ стихииSQALab
 
API. Серебряная пуля в магазине советов
API. Серебряная пуля в магазине советовAPI. Серебряная пуля в магазине советов
API. Серебряная пуля в магазине советовSQALab
 
Добиваемся эффективности каждого из 9000+ UI-тестов
Добиваемся эффективности каждого из 9000+ UI-тестовДобиваемся эффективности каждого из 9000+ UI-тестов
Добиваемся эффективности каждого из 9000+ UI-тестовSQALab
 
Делаем автоматизацию проектных KPIs
Делаем автоматизацию проектных KPIsДелаем автоматизацию проектных KPIs
Делаем автоматизацию проектных KPIsSQALab
 
Вредные привычки в тест-менеджменте
Вредные привычки в тест-менеджментеВредные привычки в тест-менеджменте
Вредные привычки в тест-менеджментеSQALab
 
Мощь переполняет с JDI 2.0 - новая эра UI автоматизации
Мощь переполняет с JDI 2.0 - новая эра UI автоматизацииМощь переполняет с JDI 2.0 - новая эра UI автоматизации
Мощь переполняет с JDI 2.0 - новая эра UI автоматизацииSQALab
 
Как hh.ru дошли до 500 релизов в квартал без потери в качестве
Как hh.ru дошли до 500 релизов в квартал без потери в качествеКак hh.ru дошли до 500 релизов в квартал без потери в качестве
Как hh.ru дошли до 500 релизов в квартал без потери в качествеSQALab
 
Стили лидерства и тестирование
Стили лидерства и тестированиеСтили лидерства и тестирование
Стили лидерства и тестированиеSQALab
 
"Давайте не будем про качество"
"Давайте не будем про качество""Давайте не будем про качество"
"Давайте не будем про качество"SQALab
 
Apache.JMeter для .NET-проектов
Apache.JMeter для .NET-проектовApache.JMeter для .NET-проектов
Apache.JMeter для .NET-проектовSQALab
 
Тестирование геолокационных систем
Тестирование геолокационных системТестирование геолокационных систем
Тестирование геолокационных системSQALab
 
Лидер или босс? Вот в чем вопрос
Лидер или босс? Вот в чем вопросЛидер или босс? Вот в чем вопрос
Лидер или босс? Вот в чем вопросSQALab
 
От Зефира в коробке к Structure Zephyr или как тест-менеджеру перекроить внут...
От Зефира в коробке к Structure Zephyr или как тест-менеджеру перекроить внут...От Зефира в коробке к Structure Zephyr или как тест-менеджеру перекроить внут...
От Зефира в коробке к Structure Zephyr или как тест-менеджеру перекроить внут...SQALab
 

More from SQALab (20)

Готовим стажировку
Готовим стажировкуГотовим стажировку
Готовим стажировку
 
Куда приводят мечты? или Искусство развития тестировщика
Куда приводят мечты? или Искусство развития тестировщикаКуда приводят мечты? или Искусство развития тестировщика
Куда приводят мечты? или Искусство развития тестировщика
 
Оптимизация Selenium тестов и ускорение их поддержки
Оптимизация Selenium тестов и ускорение их поддержкиОптимизация Selenium тестов и ускорение их поддержки
Оптимизация Selenium тестов и ускорение их поддержки
 
Автоматизация 0.0: 0 - бюджет, 0 - опыт программирования
Автоматизация 0.0: 0 - бюджет, 0 - опыт программированияАвтоматизация 0.0: 0 - бюджет, 0 - опыт программирования
Автоматизация 0.0: 0 - бюджет, 0 - опыт программирования
 
Нагрузочное тестирование нестандартных протоколов с использованием Citrix и J...
Нагрузочное тестирование нестандартных протоколов с использованием Citrix и J...Нагрузочное тестирование нестандартных протоколов с использованием Citrix и J...
Нагрузочное тестирование нестандартных протоколов с использованием Citrix и J...
 
Continuous performance testing
Continuous performance testingContinuous performance testing
Continuous performance testing
 
Конфиги вместо костылей. Pytestconfig и зачем он нужен
Конфиги вместо костылей. Pytestconfig и зачем он нуженКонфиги вместо костылей. Pytestconfig и зачем он нужен
Конфиги вместо костылей. Pytestconfig и зачем он нужен
 
Команда чемпионов в ИТ стихии
Команда чемпионов в ИТ стихииКоманда чемпионов в ИТ стихии
Команда чемпионов в ИТ стихии
 
API. Серебряная пуля в магазине советов
API. Серебряная пуля в магазине советовAPI. Серебряная пуля в магазине советов
API. Серебряная пуля в магазине советов
 
Добиваемся эффективности каждого из 9000+ UI-тестов
Добиваемся эффективности каждого из 9000+ UI-тестовДобиваемся эффективности каждого из 9000+ UI-тестов
Добиваемся эффективности каждого из 9000+ UI-тестов
 
Делаем автоматизацию проектных KPIs
Делаем автоматизацию проектных KPIsДелаем автоматизацию проектных KPIs
Делаем автоматизацию проектных KPIs
 
Вредные привычки в тест-менеджменте
Вредные привычки в тест-менеджментеВредные привычки в тест-менеджменте
Вредные привычки в тест-менеджменте
 
Мощь переполняет с JDI 2.0 - новая эра UI автоматизации
Мощь переполняет с JDI 2.0 - новая эра UI автоматизацииМощь переполняет с JDI 2.0 - новая эра UI автоматизации
Мощь переполняет с JDI 2.0 - новая эра UI автоматизации
 
Как hh.ru дошли до 500 релизов в квартал без потери в качестве
Как hh.ru дошли до 500 релизов в квартал без потери в качествеКак hh.ru дошли до 500 релизов в квартал без потери в качестве
Как hh.ru дошли до 500 релизов в квартал без потери в качестве
 
Стили лидерства и тестирование
Стили лидерства и тестированиеСтили лидерства и тестирование
Стили лидерства и тестирование
 
"Давайте не будем про качество"
"Давайте не будем про качество""Давайте не будем про качество"
"Давайте не будем про качество"
 
Apache.JMeter для .NET-проектов
Apache.JMeter для .NET-проектовApache.JMeter для .NET-проектов
Apache.JMeter для .NET-проектов
 
Тестирование геолокационных систем
Тестирование геолокационных системТестирование геолокационных систем
Тестирование геолокационных систем
 
Лидер или босс? Вот в чем вопрос
Лидер или босс? Вот в чем вопросЛидер или босс? Вот в чем вопрос
Лидер или босс? Вот в чем вопрос
 
От Зефира в коробке к Structure Zephyr или как тест-менеджеру перекроить внут...
От Зефира в коробке к Structure Zephyr или как тест-менеджеру перекроить внут...От Зефира в коробке к Structure Zephyr или как тест-менеджеру перекроить внут...
От Зефира в коробке к Structure Zephyr или как тест-менеджеру перекроить внут...
 

Appium для народа

  • 1. Черемушкин Дмитрий инженер по автоматизации тестирования ПО Scalable eCommerce Platform Solutions Обо мнеОбо мне 6+ лет в тестировании ПО ручное | автоматизированное настольное | веб | мобильное автоматизация рутинных действий в QA-процессах, интеграция инструментов Черемушкин Дмитрий 1
  • 2. 2 Постановка задачиПостановка задачи Имеется: фреймворк, основанный на стеке технологий: + автоматизированные тесты для eCommerce веб-сайта ~ 2000 тесткейсов • Firefox, Chrome, IE • локальный и удаленный запуск
  • 3. 3 1 Запустить имеющиеся тесты (в Android Browser и Mobile Safari) Разработать новые тесты (мобильная версия сайта + Android-приложение) 2 Необходимо: на мобильных ОС Android и iOS Постановка задачиПостановка задачи
  • 4. 4 Этапы решения задачиЭтапы решения задачи 11 устранение проблем + завершение интеграции в фреймворк создание proof of concept + выявление проблем выбор инструмента тестирования на мобильных платформах 22 33
  • 5. 5 Выбор инструментаВыбор инструмента Требования: open-source решение; поддержка Java и WebDriver API; поддержка ОС Android и iOS; автоматизация приложений и браузеров; работа на эмуляторах и физических устройствах; активное развитие, наличие документации
  • 7. 7 Выбор инструментаВыбор инструмента iOS Android Java WebDriver API Эмуля- торы Устройства Keep It Functional ✓ ✗ ✗ ObjectiveC ✗ ✓ ✗ Frank ✓ ✗ ✗ Ruby + Cucumber ✗ ✓ ✗ Instruments (Apple) ✓ ✗ ✗ JavaScript ✗ ✓ ✓ MonkeyTalk ✓ ✓ ✗ свой язык + JavaScript ✗ ✓ ✓ uiautomator (Google) ✗ ✓ ✓ ✗ ✓ ✓
  • 8. 8 Выбор инструментаВыбор инструмента iOS Android Java WebDriver API Эмуля- торы Устройства Robotium ✓ ✓ ✓ ✗ ✓ ✓ Calabash ✓ ✓ ~ Cucumber; Ruby gems ✗ ✓ ✓ AndroidDriver (Selenium) ✗ ~ только браузер ✓ ✓ ✓ ✓ Selendroid ✗ ✓ ✓ ✓ ✓ ✓ ios–driver ✓ ✗ ✓ ✓ ✓ ~ только приложения Appium ✓ ✓ ✓ ✓ ✓ ✓
  • 9. 9 Выбор инструментаВыбор инструмента браузеры & приложения браузеры & приложения
  • 10. 10 Appium: преимуществаAppium: преимущества лёгкость внесения модификаций в серверную часть работает без «агентов» в приложении большой спектр поддерживаемых языков распределённый запуск тестов (SeleniumGrid) кросс-платформенность тестов
  • 12. 12 Proof of concept: первый запускProof of concept: первый запуск Вручную: вернуть исходное состояние системы Вручную: посмотреть Appium-логи report stories mvn clean test Вручную: запустить Appium Вручную: Узнать UDID (для iOS-устройств)
  • 13. 13 Appium: общие проблемыAppium: общие проблемы ✗ в гибридных приложениях нужно переключаться между native и webview частями ✗ между тест-кейсами cookies браузера не очищаются ✗ Android: js-метод `click()` не работает ✗ iOS: не снимаются скриншоты ✗ нет отката к “чистому” состоянию
  • 14. 14 Appium: проблемы интеграцииAppium: проблемы интеграции ✗ Maven не запускает Appium автоматически ✗ разные “логи” у Maven и Appium ✗ iOS–устройства: нужно указывать UDID при запуске ✗ Android: Appium не запускает GenyMotion–эмулятор
  • 15. 15 Примеры решений:Примеры решений: запуск Appiumзапуск Appium <profile> <id>mobile_unix</id> <activation> <property><name>mobile</name></property> <os><family>!windows</family></os> </activation> <build> <plugins> ... <profile> <id>mobile_unix</id> <activation> <property><name>mobile</name></property> <os><family>!windows</family></os> </activation> <build> <plugins> ... нет Appium-плагина для Maven✗
  • 16. 16 Примеры решений:Примеры решений: запуск Appiumзапуск Appium <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.2.1</version> <executions><execution> <id>init</id> <phase>validate</phase> <goals><goal>exec</goal></goals> <configuration> <executable>sh</executable> <environmentVariables> <platform>${mobile}</platform> <isDevice>${device}</isDevice> </environmentVariables> <commandlineArgs>-c 'source ./main.sh; launch_appium'</commandlineArgs> </configuration> </execution></executions> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.2.1</version> <executions><execution> <id>init</id> <phase>validate</phase> <goals><goal>exec</goal></goals> <configuration> <executable>sh</executable> <environmentVariables> <platform>${mobile}</platform> <isDevice>${device}</isDevice> </environmentVariables> <commandlineArgs>-c 'source ./main.sh; launch_appium'</commandlineArgs> </configuration> </execution></executions> </plugin>
  • 17. 17 Примеры решений: гибридные приложения public class ShopScreen extends CommonMobileScreen { private ElementLocator txtScreenTitle = new ElementLocator ("Screen Title", "NATIVE_APP", By.xpath("//*[@id='title']"); public ShopScreen(WebDriverProvider driverProvider) { super(driverProvider); addElements(new MobileElement[]{txtScreenTitle, lnkShopCategory}); } } public class ShopScreen extends CommonMobileScreen { private ElementLocator txtScreenTitle = new ElementLocator ("Screen Title", "NATIVE_APP", By.xpath("//*[@id='title']"); public ShopScreen(WebDriverProvider driverProvider) { super(driverProvider); addElements(new MobileElement[]{txtScreenTitle, lnkShopCategory}); } } private MobileElement txtScreenTitle = new MobileElement ("Screen Title | xpath=//*[@id='title'] | NATIVE_APP"); private MobileElement lnkShopCategory = new MobileElement ("Category link | xpath=//div[text()='%s'] | WEBVIEW"); Native и Webview элементы – в разных фреймах✗
  • 18. 18 Примеры решений:Примеры решений: гибридные приложениягибридные приложения public class CommonMobileMethods extends WebDriverPage { private List<ElementLocator> elements = new ArrayList<ElementLocator>(); public ElementLocator getElementLocatorByName(String name) { for (MobileElement element : getElements()) { if (element.getName().equals(name)) { this.switchTo().window(element.getType()); return element; } } fail("[ERROR] Element '" + name + "' is not defined on '" + MobileScreens.getCurrentScreen() + '" screen."); return; } } public class CommonMobileMethods extends WebDriverPage { private List<ElementLocator> elements = new ArrayList<ElementLocator>(); public ElementLocator getElementLocatorByName(String name) { for (MobileElement element : getElements()) { if (element.getName().equals(name)) { this.switchTo().window(element.getType()); return element; } } fail("[ERROR] Element '" + name + "' is not defined on '" + MobileScreens.getCurrentScreen() + '" screen."); return; } } this.switchTo().window(element.getType()); public MobileElement getElementLocatorByName(String name) {
  • 19. 19 Примеры решений:Примеры решений: замена javascript `click()` на Androidзамена javascript `click()` на Android public class CommonMethods extends WebDriverPage { public void jsClickElementByLoc(By loc) { if (isLocatorPresentOnPage(loc)) { WebElement element = findElement(loc); if (isBrowser("android")) { new TouchActions(getdriver()).singleTap(element).perform(); } else { JavascriptExecutor js = (JavascriptExecutor) getDriver(); js.executeScript("arguments[0].click()", element); } } } public class CommonMethods extends WebDriverPage { public void jsClickElementByLoc(By loc) { if (isLocatorPresentOnPage(loc)) { WebElement element = findElement(loc); if (isBrowser("android")) { new TouchActions(getdriver()).singleTap(element).perform(); } else { JavascriptExecutor js = (JavascriptExecutor) getDriver(); js.executeScript("arguments[0].click()", element); } } } if (isBrowser("android")) { new TouchActions(getdriver()).singleTap(element).perform(); Android: JavaScript-клик не работает✗
  • 20. 20 Примеры решений:Примеры решений: снимки экрана на iOSснимки экрана на iOS static class ScreenshootingRemoteWebDriver extends RemoteWebDriver implements TakesScreenshot { private static final String IOS_SCREENSHOT_CMD = "mobile :getScreenshot”; public <X> X getScreenshotAs(OutputType<X> target) throws WebDriverException { String base64 = ""; if (isBrowser("ios")) { base64 = execute(IOS_SCREENSHOT_CMD).getValue().toString(); } else { base64 = execute(DriverCommand.SCREENSHOT).getValue().toString(); } return target.convertFromBase64Png(base64); } static class ScreenshootingRemoteWebDriver extends RemoteWebDriver implements TakesScreenshot { private static final String IOS_SCREENSHOT_CMD = "mobile :getScreenshot”; public <X> X getScreenshotAs(OutputType<X> target) throws WebDriverException { String base64 = ""; if (isBrowser("ios")) { base64 = execute(IOS_SCREENSHOT_CMD).getValue().toString(); } else { base64 = execute(DriverCommand.SCREENSHOT).getValue().toString(); } return target.convertFromBase64Png(base64); } if (isBrowser("ios")) { base64 = execute(IOS_SCREENSHOT_CMD).getValue().toString(); } else { base64 = execute(DriverCommand.SCREENSHOT).getValue().toString(); } private static final String IOS_SCREENSHOT_CMD = "mobile :getScreenshot”; iOS: стандартная функция не снимает скриншоты✗
  • 21. 21 Примеры решений:Примеры решений: удаление приложенийудаление приложений public class BaseStoriesRunner extends JUnitStories { protected static final String PROPERTY_MOBILE = "mobile”; @Test public void run() throws Throwable { try { beforeRun(); getEmbedder().runStoriesAsPaths(storyPath); } finally { afterRun(); } } protected void afterRun() { if (StringUtils.isNotBlank(System.getProperty(PROPERTY_MOBILE))) { uninstallMobileApps(); } } } public class BaseStoriesRunner extends JUnitStories { protected static final String PROPERTY_MOBILE = "mobile”; @Test public void run() throws Throwable { try { beforeRun(); getEmbedder().runStoriesAsPaths(storyPath); } finally { afterRun(); } } protected void afterRun() { if (StringUtils.isNotBlank(System.getProperty(PROPERTY_MOBILE))) { uninstallMobileApps(); } } } protected void afterRun() { if (StringUtils.isNotBlank(System.getProperty(PROPERTY_MOBILE))) { uninstallMobileApps(); } } afterRun(); Нет отката к исходному состоянию✗
  • 22. 22 Примеры решений:Примеры решений: удаление приложенийудаление приложений public class MobileUtils { public static void uninstallMobileApps() { executeShCommand(UNINSTALL_APPS_COMMAND); } private static void RunCommand(String command) { try { String line; Process p = new ProcessBuilder(command).start(); BufferedReader input = new BufferedReader( new InputStreamReader(p.getInputStream())); while ((line = input.readLine()) != null) { System.out.println(line); } input.close(); } catch (Exception err) { err.printStackTrace(); } } } public class MobileUtils { public static void uninstallMobileApps() { executeShCommand(UNINSTALL_APPS_COMMAND); } private static void RunCommand(String command) { try { String line; Process p = new ProcessBuilder(command).start(); BufferedReader input = new BufferedReader( new InputStreamReader(p.getInputStream())); while ((line = input.readLine()) != null) { System.out.println(line); } input.close(); } catch (Exception err) { err.printStackTrace(); } } } public static void uninstallMobileApps() { if isBrowser("ios") { RunCommand(IOS_UNINSTALL_APPS); } if isBrowser("android") { RunCommand(IOS_UNINSTALL_APPS_COMMAND); } } Process p = new ProcessBuilder(command).start();
  • 23. 23 Примеры решений:Примеры решений: удаление приложенийудаление приложений public class MobileUtils { private final String SEPARATOR = "; "; private final String PROPERTY_ANDROID_APP_PACKAGE = "android.appPackage"; private final String PROPERTY_IOS_APP_BUNDLE = "ios.appBundle"; private final String ANDROID_SELENDROID_PACKAGE = "io.selendroid"; private final String ANDROID_BROWSER_PACKAGE = "io.selendroid.androiddriver"; private final String ANDROID_UNLOCK_PACKAGE = "io.appium.unlock"; private final String IOS_SAFARILAUNCHER_BUNDLE = "com.bytearc.SafariLauncher"; private final String UNINSTALL_APPS_COMMAND = ADB_PATH +" uninstall "+ System.getProperty(ANDROID_APP_PACKAGE) + QUIET + ADB_PATH +" uninstall "+ ANDROID_BROWSER_PACKAGE + QUIET + ADB_PATH +" uninstall "+ ANDROID_SELENDROID_PACKAGE + QUIET + ADB_PATH +" uninstall "+ ANDROID_UNLOCK_PACKAGE + QUIET + FRUITSTRAP_PATH +" uninstall --bundle "+ System.getProperty(IOS_APP_BUNDLE) + QUIET + } public class MobileUtils { private final String SEPARATOR = "; "; private final String PROPERTY_ANDROID_APP_PACKAGE = "android.appPackage"; private final String PROPERTY_IOS_APP_BUNDLE = "ios.appBundle"; private final String ANDROID_SELENDROID_PACKAGE = "io.selendroid"; private final String ANDROID_BROWSER_PACKAGE = "io.selendroid.androiddriver"; private final String ANDROID_UNLOCK_PACKAGE = "io.appium.unlock"; private final String IOS_SAFARILAUNCHER_BUNDLE = "com.bytearc.SafariLauncher"; private final String UNINSTALL_APPS_COMMAND = ADB_PATH +" uninstall "+ System.getProperty(ANDROID_APP_PACKAGE) + QUIET + ADB_PATH +" uninstall "+ ANDROID_BROWSER_PACKAGE + QUIET + ADB_PATH +" uninstall "+ ANDROID_SELENDROID_PACKAGE + QUIET + ADB_PATH +" uninstall "+ ANDROID_UNLOCK_PACKAGE + QUIET + FRUITSTRAP_PATH +" uninstall --bundle "+ System.getProperty(IOS_APP_BUNDLE) + QUIET + } private final String ANDROID_UNINSTALL_APPS_COMMAND = "adb uninstall " + System.getProperty(ANDROID_APP_PACKAGE) + SEPARATOR + "adb uninstall " + ANDROID_BROWSER_PACKAGE + SEPARATOR + "adb uninstall " + ANDROID_SELENDROID_PACKAGE + SEPARATOR + "adb uninstall " + ANDROID_UNLOCK_PACKAGE; private final String IOS_UNINSTALL_APPS_COMMAND = "fruitstrap uninstall --bundle " + IOS_SAFARILAUNCHER_BUNDLE + SEPARATOR + "fruitstrap uninstall --bundle " + System.getProperty(IOS_APP_BUNDLE);
  • 24. 24 Примеры решений:Примеры решений: вывод Appium-ошибоквывод Appium-ошибок public class CustomPerStoryWebDriverSteps extends PerStoryWebDriverSteps { public static final String PROPERTY_MOBILE = "mobile"; @AfterScenario(uponOutcome = AfterScenario.Outcome.FAILURE) public void afterScenarioFailure(UUIDExceptionWrapper uuidWrappedFailure){ if (uuidWrappedFailure instanceof PendingStepFound) { return; } if (StringUtils.isNotBlank(System.getProperty(PROPERTY_MOBILE))) { MobileUtils.outputAppiumErrors(); } } } public class CustomPerStoryWebDriverSteps extends PerStoryWebDriverSteps { public static final String PROPERTY_MOBILE = "mobile"; @AfterScenario(uponOutcome = AfterScenario.Outcome.FAILURE) public void afterScenarioFailure(UUIDExceptionWrapper uuidWrappedFailure){ if (uuidWrappedFailure instanceof PendingStepFound) { return; } if (StringUtils.isNotBlank(System.getProperty(PROPERTY_MOBILE))) { MobileUtils.outputAppiumErrors(); } } } if (StringUtils.isNotBlank(System.getProperty(PROPERTY_MOBILE))) { MobileUtils.outputAppiumErrors(); } @AfterScenario(uponOutcome = AfterScenario.Outcome.FAILURE) Appium-ошибки не показываются в логе Maven’а✗
  • 25. 25 Примеры решений:Примеры решений: вывод Appium-ошибоквывод Appium-ошибок public class MobileUtils { private final String APPIUM_LOG_PATH = "./target/mobile/appium.log"; private final String APPIUM_FULL_LOG_PATH = "./target/mobile/appium_full.log"; private static final String OUTPUT_APPIUM_ERRORS = "errors=$(grep 'error: |Error :|STDERR' "+ APPIUM_LOG_PATH +");" + "[ -n $errors ] && echo $errors | sed s/^/'[ERROR] appium.log: '/gn" + " && cat ”+ APPIUM_LOG_PATH +" >>"+ APPIUM_FULL_LOG_PATH + " && echo '' >”+ APPIUM_LOG_PATH; public static void outputAppiumErrors() { executeShCommand(OUTPUT_APPIUM_ERRORS); } } public class MobileUtils { private final String APPIUM_LOG_PATH = "./target/mobile/appium.log"; private final String APPIUM_FULL_LOG_PATH = "./target/mobile/appium_full.log"; private static final String OUTPUT_APPIUM_ERRORS = "errors=$(grep 'error: |Error :|STDERR' "+ APPIUM_LOG_PATH +");" + "[ -n $errors ] && echo $errors | sed s/^/'[ERROR] appium.log: '/gn" + " && cat ”+ APPIUM_LOG_PATH +" >>"+ APPIUM_FULL_LOG_PATH + " && echo '' >”+ APPIUM_LOG_PATH; public static void outputAppiumErrors() { executeShCommand(OUTPUT_APPIUM_ERRORS); } } private static final String OUTPUT_APPIUM_ERRORS = "errors=$(grep 'error: |Error :|STDERR' " + APPIUM_LOG_PATH + ");" + "[ -n $errors ] && echo $errors | sed s/^/'[ERROR] appium.log: '/gn" + " && cat " + APPIUM_LOG_PATH + " >>" + APPIUM_FULL_LOG_PATH + " && echo '' >" + APPIUM_LOG_PATH; public static void outputAppiumErrors() { executeShCommand(OUTPUT_APPIUM_ERRORS); }
  • 26. 26 откат к «чистому» cостоянию при ошибке: Appium-лог + скриншот✗ Итоговый фреймворк:Итоговый фреймворк: схема работысхема работы очистка cookies запуск тестов запуск Appium сервера [и эмулятора] сборка тестов
  • 27. 27 mobile = (?: android_browser | ios_safari | android_app | ios_app ) $ cat mobile.properties ios.app = TestedApp.ipa ios.simulatorType = iPhone (3.5 inch) ios.version = 7.0 android.app = TestedApp.apk android.waitActivity = com.app.MainActivity android.vmType = GenyMotion android.vmName = Nexus One - 4.2.2 - API 17 - 480x800 mobile = (?: android_browser | ios_safari | android_app | ios_app ) $ cat mobile.properties ios.app = TestedApp.ipa ios.simulatorType = iPhone (3.5 inch) ios.version = 7.0 android.app = TestedApp.apk android.waitActivity = com.app.MainActivity android.vmType = GenyMotion android.vmName = Nexus One - 4.2.2 - API 17 - 480x800 Итоговый фреймворк:Итоговый фреймворк: параметры запускапараметры запуска $ mvn clean test -Dmobile=android_app -Ddevice=false –Dsuite=MobileTestSuite $ mvn clean test -Dmobile=android_app -Ddevice=false –Dsuite=MobileTestSuite $ cat mobile.properties
  • 28. 28 ЗаключениеЗаключение запуск существующих веб-тестов в мобильных браузерах разработка новых кросс-платформенных тестов для мобильных сайтов и приложений 11 использование принятых на проекте практик в мобильном тестировании 22 33 Возможности полученного решения:
  • 29. 29 Перспективы развитияПерспективы развития расширение корпоративной инфраструктуры SeleniumGrid нодами для мобильного тестирования реализация решения в виде Maven-плагина для интеграции в другие проекты добавление возможности мобильного тестирования на ОС Windows Phone и Windows 8 увеличение количества мобильных браузеров, поддерживаемых фреймворком
  • 30. Scalable eCommerce Platform SolutionsScalable eCommerce Platform Solutions Dmitry.Cheremushkin@gmail.com DCheremushkin@griddynamics.com