Тестовые случаи ActivityInstrumentationTestCase2 И Robotium зависают до тех пор, пока на эмуляторе не будет нажата клавиша «назад/домой». ПОЧЕМУ?

Я разрабатываю приложение графического калькулятора с одним действием. (Android API 10) Макет довольно сложный: более 40 кнопок занимают нижнюю половину экрана, а макет кадра — в верхней части экрана. Макет кадра является подклассом «ScreenFrame», который содержит «экран» калькулятора. КАЖДОЕ представление/группа просмотра, которое отображается в ScreenFrame, является пользовательским представлением/группой просмотра, которое отображает вычисления, которые выполняет пользователь. Вспомните графический калькулятор TI, где все выражение можно увидеть с символами операций...

Я пишу тесты JUnit, в основном производя подклассы AndroidTestCase, потому что мне нужен контекст только для тестирования огромной части кода, а не всей инфраструктуры активности. Однако я приближаюсь к тому моменту, когда я хотел бы начать писать функциональные тестовые примеры, и некоторые части приложения требуют, чтобы вся структура деятельности работала.

Итак, вот проблема, которая поставила меня в тупик. Сначала я покажу код тестового примера

public class CommandTest extends ActivityInstrumentationTestCase2<Calculator> {

    private Calculator _calculator;

    public CommandTest(){
        super(Calculator.class);
    }

    @Override
    protected void setUp() throws Exception {
        setActivityInitialTouchMode(true);
        _calculator = getActivity();
        super.setUp();
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
        _calculator.finish(); // doesn't make a difference if this line is there or not
    }

    public void testCircleBadSyntax1() {
        _calculator.runOnUiThread(new Runnable() {
            @Override public void run() {
                Button twoButton = (Button) _calculator.findViewById(R.id.twoButton);
                twoButton.performClick();
                Button addButton = (Button) _calculator.findViewById(R.id.addButton);
                addButton.performClick();
                Button nineButton = (Button) _calculator.findViewById(R.id.nineButton);
                nineButton.performClick();
                Button enterButton = (Button) _calculator.findViewById(R.id.equalsButton);
                enterButton.performClick();
             }
        });
        Instrumentation inst = getInstrumentation();
        inst.waitForIdleSync();

        _calculator.runOnUiThread(new Runnable() {
             @Override public void run() {
                 ScreenFrame screenFrame = (ScreenFrame) _calculator.findViewById(R.id.screenFrame);
                 assertNotNull(screenFrame);
                 AnswerSymbolGroup answer = screenFrame.getLastAnswer();
                 INumber number = answer.getNumberAnswer();
                 assertEquals(number.getValueInt(), 11); 
            }
    });
        _calculator.finish();
    }
}

Я только что показал вам, как я все настраивал, и один пример теста выше. Все тестовые случаи похожи, и проблема не в том, что тестируется... Основная проблема в том, что когда я запускаю тест через eclipse, тест просто зависает на первом экземпляре тестового примера на неопределенный срок (я пытался оставить его для в то время как просто посмотреть, и он просто сидел с синей стрелкой на первом случае в течение 45+ минут). Крайне странно то, что когда я нажимаю кнопку HOME или кнопку «Назад» на эмуляторе, запускается тестовый пример. И дает соответствующий ответ. Вы не видите никаких изменений экрана или других вещей, которые вы должны видеть при нажатии кнопок, но тестовый пример работает так, как должен. это означает, что он проходит или терпит неудачу в зависимости от кода, который я тестирую. Затем бегун тестов зависает на следующем тесте, пока я снова не нажму кнопку «Назад» или «Домой».

Это не работающее решение. Я хотел бы иметь от десяти до двадцати случаев (иногда намного больше) в тестовом файле, и я хотел бы, чтобы все они выполнялись успешно без необходимости нажимать что-либо на эмуляторе, тем более что у меня есть Jenkins CI, который я использовать для всех других тестов, которые у меня есть без проблем.

Поэтому я подумал, что фреймворк вроде robotium для этих типов тестов будет лучше подходить для обработки этих типов тестов.

У меня такая же проблема с роботиумом. Когда я запускаю тестовый пример robotium с отображением домашнего экрана на эмуляторе, тестовый пример запускается, выводит экран калькулятора, а затем зависает на неопределенный срок. Когда я нажимаю кнопку «Назад», а затем снова открываю приложение, тестовый пример начинается с самого начала и продолжает работать так, как должен, то есть он проходит, если код, который он тестирует, правильный, а если нет. Однако вы можете увидеть соответствующие изменения в корпусах роботиума. Например, если данный тест был скорректирован так, чтобы использовать переменную соло для нажатия кнопок и ничего из runOnUiThreads, на экране появится двойка после нажатия кнопки двойки, затем плюс, девятка и одиннадцать после ввода. нажимается. В следующем тестовом случае происходит то же самое, он зависает на неопределенное время. Когда я нажимаю «Назад» или «Домой», а затем снова открываю приложение, тест продолжается. В каждом тестовом примере я должен повторять этот процесс. Я не пробовал запускать эти тесты в своем блоке jenkins (все еще разрабатываю, как запустить тест роботиума без головы).

Я был в тупике в течение нескольких дней и не чувствую, что должен тратить больше времени, пытаясь понять это. Кто-нибудь еще сталкивался с таким поведением.

Обычно я ненавижу использовать отладчик для поиска ошибок, потому что считаю, что это занимает гораздо больше времени, чем написание тестов и запись соответствующего вывода в LOGCAT. Однако я попытался запустить отладчик в этой ситуации, чтобы выяснить, где что-то зависает. Я знаю, что тестовый пример зависает в строке getActivity()... Я дохожу до точки в отладчике, где я зацикливаюсь в основном цикле. Методы onCreate(), onStart() и onResume() завершены, и весь экран виден, но как только это происходит, он зависает, пока я не нажму кнопку «Назад» или кнопку «Домой».

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

/** Добавлено После того, как пришли первые ДВА ответа **/ К первому ответу я уже пытался поместить activity.finish() в метод tearDown(), это не имеет значения...

Что касается второго ответа, я перепробовал все возможные варианты размещения super.setUp() и super.tearDown() в тестах setUp и tearDown(), не включая их в качестве одного из вариантов.

Я попытался более тщательно запустить метод getActivity() отладчика и могу сказать, что код застревает в классе Instrumentation в методе startActivitySync(Intentintent).

в строке 391 запускается getTargetContext().startActivity(intent), а затем он переходит к следующей части блокировки синхронизации...

getTargetContext().startActivity(intent);

do{
    try{
        mSync.wait();
    } catch(InterruptedException e){
    }
}while(mWaitingActivities.contains(aw));

return aw.activity;

person phriendtj    schedule 21.11.2013    source источник
comment
Возможно ли, что бесконечно повторяющаяся анимация в представлении может вызвать зависание, а не зависание?   -  person phriendtj    schedule 22.11.2013
comment
У меня такая же проблема. вы получили решение?   -  person ericyoung    schedule 21.05.2014


Ответы (3)


В вашем методе tearDown вам нужно вызвать _calculator.finish();

Для тестов, которые открывают несколько активностей, в robotium есть удобный метод для завершения всех из них: solo.finishOpenedActivities();

person Dave C    schedule 21.11.2013
comment
Я не показал этого в коде, который я опубликовал, но я вызываю эти методы в методе tearDown(), и в моем приложении есть только одно действие.... - person phriendtj; 21.11.2013

Я не уверен, поможет ли это вам, однако вы должны вызывать super.setUp(); в начале метода setUp и super.tearDown(); в конце метода tearDown. Вы также можете попробовать удалить их.

Кстати, звонить setActivityInitialTouchMode(false); не имеет смысла, потому что:

Если вы не вызовете это, сенсорный режим будет ложным. Если вы вызываете это после того, как ваша активность была запущена, это не будет иметь никакого эффекта.

person maszter    schedule 21.11.2013

У меня была аналогичная проблема. Я мог бы решить свою проблему, поместив метод setAdapter() в класс AsyncTask.

person Leonardo    schedule 10.12.2013