Настаиваю библиотеку Jacoco. Пишу код в Android Studio 3.0. Есть MainActivity: package houzz.com.hellojacoco public class MainActivity extends AppCompatActivity implements View.OnClickListener { private TextView text @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) findViewById(R.id.button).setOnClickListener(this) findViewById(R.id.hide).setOnClickListener(this) text = findViewById(R.id.text) } @Override public void onClick(View v) { if (v.getId() == R.id.button) { text.setText("Hello World!") } else { v.setVisibility(View.GONE) } } } Для экрана есть тест MainActivityTest: @RunWith(AndroidJUnit4.class) @LargeTest public class MainActivityTest { @Rule public final ActivityTestRule rule = new ActivityTestRule<>(MainActivity.class) @Test public void test1() { onView(withId(R.id.hide)).perform(click()) onView(withId(R.id.hide)).check(matches(not(isDisplayed()))) } @Test public void test2() { onView(withId(R.id.button)).perform(click()) onView(withId(R.id.text)).check(matches(withText("Hello World!"))) } } В gradle подключил создание отчетов о покрытии кода, согласно ответу: android { buildTypes { debug { testCoverageEnabled = true } } } Далее запустил задачу проверки: ./gradlew createDebugCoverageReport В отчете по пути hellojacoco\app\build eports\coverage\debug\index.html получаю результат в 0% покртытия тестами. Как покрыть код Activity на 100%? Может по другому настроить? Стандартный отчет из Android Studio, так же показывает 0% P.S. Пробовал делать по разным статьям, например по этой. Ни один результат не учитывает тесты из папкиAndroidTest. Максимум JUnit тесты учитываются. Так же в этой статье есть ссылка на GitHub, а так же ветка с обновлением для Android Stduio 3.0, но у меня все равно отчеты не получаются корректно. P.S.S. Оказывается основная проблемма была в телефоне, отчет с телефона Samsung получить не получается, получил через эмулятор. Но работатет все равно не до конца корректно. Вот как сейчас выглядит покрытие Activity:
То есть в отчет включается только test2, а должен и test1. Если удалить test2, test1 учитывается. Если тесты объединить в один, покрытие будет 100%, но если их будет много, тогда будет не удобно получать отчеты, о том какие тесты выполнились а какие нет. Ссылка на весь проект Ответ ниже помогает в некоторых моментах лучше понять вопрос, но не дает хорошего решения проблемы.
Ответ Я когда-то пробовал по вот этому настраивать. И из текста вашего вопроса не совсем понятно какую разметку и код вы используете (я про вторую кнопку - последний пример - непонятно что должно произойти по нажатию) Это помогло бы понять что не так с тестом. Но хочу отметить 2 вещи (может вам поможет): Тесты если не указан порядок исполняются в любом порядке (иначе нужно аннотировать класс теста так например @FixMethodOrder(MethodSorters.NAME_ASCENDING)) Если вы считаете что нажатие не отрабатывает по тому что провалиается тест - попробуйте заменить .check(matches(not(isDisplayed()))) на .check(doesNotExist()) Но для получения развернутого ответа - выложите пожалуйста полные исходники. UPDATED (Добавлено после проверки всех исходников) Все отлично у вас работает, но есть моменты: Какого поведения среды исполнения вы ждете при изменении видимости? v.setVisibility(View.GONE) будет выполнено в потоке UI ПОСЛЕ завершения работы onClick(). Ожидать чего то другого - невозможно. Поэетому jacoco в отчете всегда будет указывать пропущенную инструкцию - тк проверить что она была выполнена она не может физически. В условиях всегда будут пропущенные бранчи - тк оно считатет ВСЕ возможные логические состояния и состояния аргумента. Те null, невозможность вызвать метод итд. Попробуйте сделать обработчики анонимными объектами - я так проверял: findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { text.setText("Hello World!") }}) findViewById(R.id.hide).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { v.setVisibility(View.GONE) }})
В этом случае не будет пропущенных бранчей. Будет одна пропущенная инструкция (уставка видимости). И покрытие - 93%. Я думаю это лучший из возможных результатов. А вообще - я бы очень не советовал гоняться за 100% покрытием, особенно если надо "переписывать код под тесты". Ну и надо понимать - что не все корректно оно может учесть, просто в меру особенностей среды исполнения. И помнить что оно анализирует ФИНАЛЬНЫЙ скомпилированный код в байткоде. Например если вы switch-case сделаете - будет на каждый выбор по 2 бранча + если это числа то + все пропущенные - те полная хэш-таблица всех состояний. (правда там както обещали фильтр сделать такого - не проверял) UPDATED (Дополнительные пояснения по комментариям) Я вижу вы все упираетесь - попробую пояснить :) Объедините все в один тест вот так: @Test public void test1() { onView(withId(R.id.hide)).perform(click()) onView(withId(R.id.hide)).check(matches(not(isDisplayed()))) onView(withId(R.id.button)).perform(click()) onView(withId(R.id.text)).check(matches(withText("Hello World!"))) } И вы получите 100% покрытие и все будет нормально. Почему? Потому что как я уже и писал: Тесты выполняются не по порядку. У вас по обоим нажатиям срабатывает onClick() и только после его завершения меняется текст или прячется кнопка в UI потоке. Те в памяти получается при 2х раздельных тестах - 2 раздельных асинхронных вызова - и в одном из них одно отработает, в другом другое. Те в каком порядке тесты выполняются - мы не знаем, в каком порядке асинхронные вызовы и операции изменения текста и видимости произойдут - мы не знаем. Знаем только одно - это изолированные друг от друга вызовы с созданием асинхронной задачи и последующей синхронизацией с UI потоком - а в каком порядке оно будет - "как карта ляжет". Поэтому и такой результат - мы не знаем какую из 2х асинхронных операций оно анализирует. Какие есть счетчики в jacoco почитайте тут. ОБЯЗАТЕЛЬНО прочтите про анализ покрытия кода тут. И думаю потом вы поймете - что при расстановке проб jacoco - ставит их по вашему коду 'как есть'. А в реальности - там 2 асинхронных вызова + они инициируются 2мя асинхронными тестами. И + это все еще оптимизирует компилятор. Те какая 'каша' из проб и асинхронностей в результате - никто не знает. Поэтому асинхронные вызовы тестируются только в рамках ОДНОГО теста на покрытие - тк это гарантирет очередность операций. Можно еще упралять выполнением тестов espresso с помощью idling resources Но здесь мы имеем дело с работой анализатора jacoco - в тестах же нет проблем.