Определение того, какие тестовые случаи охватывали метод - PullRequest
2 голосов
/ 31 августа 2011

Текущий проект, над которым я работаю, требует, чтобы я написал инструмент, который запускает функциональные тесты в веб-приложении и выводит данные покрытия метода, записывая, какой тестовый пример прошел какой метод.

Подробности: Тестируемое веб-приложение будет приложением Java EE, работающим в контейнере сервлета (например, Tomcat).Функциональные тесты будут написаны в Selenium с использованием JUnit.Некоторые методы будут аннотированы так, чтобы они были оснащены до развертывания в тестовой среде.После выполнения тестов Selenium будет записано выполнение аннотированных методов.

Задача : Большим препятствием этого проекта является нахождение способа связать выполнение тестового примера сОбход метода, особенно то, что тесты и приложение выполняются на разных JVM, и нет способа передать имя тестового примера в приложение, а также нет возможности использовать информацию потока, чтобы связать тест с выполнением кода.

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

Ожидаемые проблемы: В этом решении предполагается, что тестовые примеры выполняются последовательно, и тестовый случай заканчивается до запуска следующего,Является ли это предположение разумным с JUnit?

Вопрос: Проще, могу ли я высказать свое мнение о предлагаемом решении и, возможно, предложения о том, как улучшить и сделать его более надежным и функциональным на большинстве JavaEE приложения?Или приводит к уже реализованным решениям?

Спасибо

Редактировать : чтобы добавить больше требований, инструмент должен уметь работать с любым приложением Java EE и требовать как минимумколичество настроек или изменений в приложении.Хотя я знаю, что это нереалистичное требование, инструмент по крайней мере не должен требовать каких-либо значительных изменений самого приложения, таких как добавление классов или строк кода.

Ответы [ 2 ]

0 голосов
/ 01 сентября 2011

Ваше предлагаемое решение кажется разумным, за исключением того, что предлагаемое решение связывает тест и запрос по времени. Я пытался делать подобные вещи раньше, и это работает. Большую часть времени. Если вы не будете писать свой код JUnit очень тщательно, у вас будет много проблем из-за различий во времени между двумя машинами или если у вас есть только одна машина, просто сопоставьте одно время с другим.

Лучшим решением было бы реализовать Tomcat Valve , который можно вставить в жизненный цикл в файле server.xml для вашего веб-приложения. Преимущество Valves заключается в том, что вы определяете их в файле server.xml, поэтому вы вообще не касаетесь веб-приложения.

Вам нужно будет реализовать invoke (). Лучше всего начать с AccessLogValve . Это реализация в AccessLogValve:

/**
 * Log a message summarizing the specified request and response, according
 * to the format specified by the <code>pattern</code> property.
 *
 * @param request Request being processed
 * @param response Response being processed
 *
 * @exception IOException if an input/output error has occurred
 * @exception ServletException if a servlet error has occurred
 */
public void invoke(Request request, Response response) throws IOException,
        ServletException {

    if (started && getEnabled()) {                
        // Pass this request on to the next valve in our pipeline
        long t1 = System.currentTimeMillis();

        getNext().invoke(request, response);

        long t2 = System.currentTimeMillis();
        long time = t2 - t1;

        if (logElements == null || condition != null
                && null != request.getRequest().getAttribute(condition)) {
            return;
        }

        Date date = getDate();
        StringBuffer result = new StringBuffer(128);

        for (int i = 0; i < logElements.length; i++) {
            logElements[i].addElement(result, date, request, response, time);
        }

        log(result.toString());
    } else
        getNext().invoke(request, response);       
}

Все, что это делает, регистрирует тот факт, что вы получили к нему доступ.

Вы бы внедрили новый клапан. Для ваших запросов вы передаете уникальный идентификатор в качестве параметра для URL, который используется для идентификации выполняемых вами тестов. Ваш клапан будет выполнять всю тяжелую работу до и после вызова (). Вы можете удалить, удалить уникальный параметр для getNext (). Invoke (), если это необходимо.

Чтобы измерить покрытие, вы можете использовать инструмент покрытия, предложенный JB Nizet, на основе уникального идентификатора, который вы передаете.

Итак, из junit, если ваш исходный вызов был

@Test void testSomething() {
    selenium.open("http://localhost/foo.jsp?bar=14");
}

Вы бы изменили это на:

@Test void testSomething() {
    selenium.open("http://localhost/foo.jsp?bar=14&testId=testSomething");
}

Тогда вы бы выбрали параметр testId в вашем клапане.

0 голосов
/ 31 августа 2011

Вы смотрели на существующие инструменты покрытия (Cobertura, Clover, Emma, ​​...). Я не уверен, что один из них сможет связать данные покрытия с тестовыми случаями, но, по крайней мере, с Cobertura, которая является открытым исходным кодом, вы могли бы сделать следующее:

  • инструмент на занятиях с кобертурой
  • развернуть инструментированное веб-приложение
  • запустить тестовый набор
    • после каждого теста вызывайте в веб-приложении URL-адрес, который сохраняет данные покрытия в некоторый файл с именем после только что проведенного теста и сбрасывает данные покрытия
  • после набора тестов создайте отчет cobertura для каждого сохраненного файла. Каждый отчет сообщит, какой код был выполнен тестом

Если вам нужен объединенный отчет, я полагаю, что не составит труда создать его из набора сохраненных файлов с использованием API-интерфейса cobertura.

...