Надежные тесты для автоматизации тестирования Android приложений с Robotium

Не так давно я закончил первую статью из цикла автоматизации мобильных приложений [http://automated-testing.info/t/nastrojka-sredy-dlya-razrabotki-android-prilozhenij-i-avtomatizaczii-na-robotium/2421][1]. Я попытался максимально полно дать информацию по установке требуемого окружения, для разработки и автоматизации тестирования NativeAndroid приложений, при помощи инструмента Robotium. 

В конце той статьи был приведен пример простого теста. Давайте еще раз взглянем на него.
``` import android.test.ActivityInstrumentationTestCase2;

import com.example.android.notepad.NotesList;
import com.jayway.android.robotium.solo.Solo;

/**

  • Add note test
  • Example of simple Robotium test
  • @author adzynia

*/
public class AddNoteTest extends ActivityInstrumentationTestCase2{

private static final String APP_PACKAGE_NAME = “com.example.android.notepad”;
protected Solo solo;

public AddNoteTest() {
super(APP_PACKAGE_NAME, NotesList.class);
}

public void setUp() throws Exception {
solo = new Solo(getInstrumentation(), getActivity());
}

public void testAddNote() throws Exception {
solo.clickOnMenuItem(“Add note”);
//Assert that NoteEditor activity is opened
solo.assertCurrentActivity(“Expected NoteEditor activity”, “NoteEditor”);
//In text field 0, add TestNote
String note = “TestNote”;
solo.enterText(0, note);
solo.goBack();
//Assert that TestNote is found
assertTrue(“Note 1 is not found”, solo.searchText(note));
}

@Override
public void tearDown() throws Exception {
//Robotium will finish all the activities that have been opened
solo.finishOpenedActivities();
}
}

<p>Ничего не понятно (или мало что понятно), скажете Вы и будете правы. &nbsp;Эти тесты выглядят только как вызов API инструмента. Набор функций, которые понимает Robotium, но не тестировщик. Что же стоит делать в таком случае? Как сделать тесты более читабельными, полезными и чтобы в них можно было как можно быстрее разобраться?</p><div>Давайте начнем с небольшой теории. Для тех, кто уже успешно занимался web автоматизацией, текст ниже можно не читать.</div><p><!--break--></p><div>&nbsp;</div><div>Существует некий подход по именованию классов и функций, который получил название DSL (DomainSpecificLanguage). В чем суть этого подхода?&nbsp;</div><div>&nbsp;</div><div>Wikipedia</div><div>Языки программирования предметной области, дополненные технологиями метапрограммирования, являются эффективным средством автоматизации разработки программного обеспечения и в настоящий момент находят широкое применение в области информационных технологий.&nbsp;</div><div>Процесс создания нового предметно-ориентированного языка состоит из трех шагов:</div><ol><li>Определение абстрактного синтаксиса.</li><li>Определение конкретного синтаксиса.</li><li>Определение правил трансформации.</li></ol><div>&nbsp;</div><div>Для тех, кто не понял: DSL это описание классов и функций в зависимости от предметного домена приложения, которое Вы разрабатываете. &nbsp;Например:</div><ul><li>DSL для подсчета зарплат.</li><li>DSL для оплаты счета.</li><li>DSL для продажи мультимедийного контента.</li></ul><div>Каждая из отраслей (доменов) содержит в себе функции с разным именованием, хотя, иногда, могут выполнять одну и ту же функциональность.</div><div>&nbsp;</div><div>Надеюсь с этим понятно.</div><div>&nbsp;</div><div>Что еще нам нужно знать для того чтобы писать хорошие тесты? Из web автоматизации большинству из нас известен паттерн PageObject (впервые его опубликовал Martin Fauler,но с немного другим названием WindowDriver).</div><div>Существует немало споров как лучше организовать эту модель и стоит ли делать ее вообще. Я поделюсь своим опытом, на основании десятка автоматизированных как веб, так и мобильных проектов. &nbsp;</div><div>&nbsp;</div><div>Так как мы будем говорить о мобильной разработке, &nbsp;то слово PageObject уже не подходит, так как у Native приложений не страницы, а экраны. Назовем, этот паттерн, условно, ScreenObject.&nbsp;</div><div>Теперь давайте представим, что экран со списком заметок (рис 1) это Java класс.&nbsp;</div><div>&nbsp;</div><div>&nbsp;<img alt="" src="/sites/default/files/images/mobile-app.jpg" style="width: 300px; height: 500px; "></div><div>Рис. 1</div><div>А все функции, которые можно выполнить на этой странице это JavaMethods. Получим, что-то вроде вот этого.&nbsp;</div><div>&nbsp;</div>

packagecom.jayway.screens;

importcom.example.android.notepad.NotesList;
importcom.example.android.notepad.R;
importcom.jayway.android.robotium.solo.Solo;

public class NotesListScreen extends BaseScreen {

publicNotesListScreen(Solo solo) {
	super(solo, NotesList.class);
}
 
public void clickAddNote() {
	//TODO: Add some logic here
}
 
publicbooleanisNotePresent(String noteName) {
	//TODO: Add some logic here
	return false;
}
 
public void clickNote(String note) {
	//TODO: Add some logic here
}
 
public void removeNote(String noteName) {
	//TODO: Add some logic here
}

}


<div>&nbsp;</div><div>То есть мы получили класс NotesListScreen с перечнем всех функций на этом экране. Функции получились пустышки, и нам нужно их реализовать. Давайте начнем с функции clickAddNote(). Добавляем Robotium вызов, который нажмет на эту кнопку. Оп, и что произошло? После нажатия на эту кнопку мы попали на совсем другой экран - AddNoteScreen.&nbsp;</div><div>Нам это так же нужно запрограммировать в методе</div><div>&nbsp;</div>

publicAddNoteScreenclickAddNote() {
getSolo().clickOnMenuItem(getSolo().getString(R.string.menu_insert));
returnnewAddNoteScreen(getSolo());
}


<div>&nbsp;</div><div>Что получилось, созданный метод будет возвращать объект уже нового экрана, у которого будут уже свои методы по работе только с экраном AddNoteScreen.</div><div>&nbsp;</div><div>Это было ключевое, дальше лишь дело техники.</div><div>&nbsp;</div><div>Как будет выглядеть конечный тест?</div>

packagecom.jayway.test;

importandroid.test.suitebuilder.annotation.Smoke;

importcom.example.android.notepad.R;
importcom.jayway.android.robotium.solo.Solo;
importcom.jayway.screens.AddNoteScreen;
importcom.jayway.screens.NotesListScreen;

public class NotePadTest extends BaseTestCase {

private static final String EDITED_TEST = "Edited Test";
private static final String NOTE_NAME = "Note 1";
 
@Smoke
public void testAddNote() throws Exception {
	NotesListScreennoteListScreen = new NotesListScreen(solo);
	assertTrue(noteListScreen.isCurrentActivityOpened());
	AddNoteScreenaddNoteScreen = noteListScreen.clickAddNote();
	addNoteScreen.assertCurrentActivity();
	addNoteScreen.typeNote(NOTE_NAME);
	noteListScreen = addNoteScreen.goBack();
	noteListScreen.assertCurrentActivity();
	assertTrue(NOTE_NAME + " is not found", noteListScreen.isNotePresent(NOTE_NAME));
}

}


<div>&nbsp;</div><div>Теперь тест стал намного читабельней, не так ли? Java код начинает выглядеть как обычный тест- кейс, при этом мы видим смену экранов по который "прыгает" пользователь.</div><div>&nbsp;</div><div>Видите как быстро, и не очень сложно мы разобрались с тем как писать правильные тесты на Robotium.</div><div>&nbsp;</div><div>Так же Вы могли заметить, что у меня появился некий базовый класс, от которого унаследован мой тест. Так же у каждого экрана есть унаследованный класс BaseScreen. Эти классы содержат в себе вспомогательные методы, для работы с тестом и экранами. Более детально мы сможем их разобрать в следующих уроках.&nbsp;</div><div>&nbsp;</div><div>Спасибо за внимание.&nbsp;</div>


  [1]: http://automated-testing.info/t/nastrojka-sredy-dlya-razrabotki-android-prilozhenij-i-avtomatizaczii-na-robotium/2421
1 лайк

Не подскажете где найти

import com.jayway.screens.AddNoteScreen;
import com.jayway.screens.NotesListScreen;

extends BaseTestCase

 

Попробуйте скачать вот здесь https://dl.dropbox.com/u/10632790/sqa-days-examples-robotium.zip 

Спасибо, работает.

Где можно посмотреть первую статью из цикла автоматизации мобильных приложений

1 лайк