Модульное тестирование с множеством вариантов использования - PullRequest
7 голосов
/ 31 июля 2009

Я работаю над Java-приложением, у которого много вариантов использования. Входами в приложение являются различные виды событий, происходящих в разное время. Этот вид ввода приводит к сотням тестовых случаев. Кто-нибудь сталкивался с таким сценарием? Удостоверьтесь ли вы, что все тестовые случаи покрыты, прежде чем делать релиз для команды QA? Итак, мой вопрос: каков наилучший подход для тестирования программ с большим количеством тестовых случаев?

Ответы [ 10 ]

14 голосов
/ 31 июля 2009

Не пытайтесь покрыть юнит-тестами все приложение с самого начала. Делайте это небольшими, постепенными шагами. Установите небольшую веху в течение недели или двух, а затем начните писать тесты для первой функциональности этой вехи. Затем начните реализовывать эту функциональность. Это должно быть примерно так:

Маленькие, пошаговые шаги

  1. Разбейте приложение на более мелкие вехи функций, которые вы можете увидеть в этот момент
  2. Выберите наиболее актуальную функцию, которая должна быть реализована на данный момент
  3. Разбейте эту функцию на более мелкие задачи
  4. Написать тест для одной из задач
  5. Запустите тест. Должно произойти сбой ( RED ). Если оно прошло, ваш тест не пройден.
  6. Начните писать наименьшее количество кода, чтобы пройти этот тест. Допускаются жестко закодированные значения.
  7. Запустить тесты ( ЗЕЛЕНЫЙ ). Они должны пройти (особенно при использовании жестко закодированных значений). Теперь вы знаете, что у вас есть страховка для будущих рефакторингов.
  8. Начните рефакторинг ( REFACTOR ) вашего кода, если это необходимо, в противном случае перейдите к шагу 4.

Подготовка к изменению

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

Как сказал Gren , вы, вероятно, путаете варианты использования с модульным тестированием. Действия, которые пользователь может выполнить с приложением, могут быть точно так же обработаны одним методом в модели предметной области. Так что ситуация может быть не такой плохой, как кажется.

Нет предварительного дизайна, даже для модульных тестов

В любом случае, не пытайтесь писать все свои тесты с самого начала. Я так и делал, и это был большой провал. Выполнив небольшие итерации (тестовый метод / реализация метода), вы станете гораздо более продуктивным и уверенным в себе. Когда вы пишете все свои тесты заранее, вы можете заметить, что из-за факторизаций, необходимых для прохождения первых тестов, вам необходимо переосмыслить весь API, который вы предусмотрели при написании тестов, в то время как написание теста, затем реализация, тест, затем реализация, и в итоге вы получите то, что называется эмерджентным дизайном. И это лучший вид дизайна. Так появились шаблоны дизайна. Шаблоны проектирования не возникли у человека, который целый день стоял и думал о способах решения проблемы.

5 голосов
/ 31 июля 2009

Если у вас есть сотни тестовых случаев, я предполагаю, что это потому, что это отражает изменчивость входных данных и требования приложения?

Если вы не пишете тесты для всех этих (известных) случаев, то как вы узнаете, предоставили ли вы желаемую функциональность?

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

4 голосов
/ 31 июля 2009

Я широко использую теории JUnit для минимизации тестовых случаев:

import org.junit.Assert;
import org.junit.Assume;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import static org.hamcrest.CoreMatchers.*;

@RunWith(Theories.class)
public class D {

    @DataPoints
    public static int[] a = {1, 2, 3, 4};
    @DataPoints
    public static int[] b = {0, 1, 2, 3, 4};

    @Theory
    public void divisible(int a, int b) {
        Assume.assumeThat(b, is(not(0)));
        System.out.format("%d / %d\n", a, b);
        int c = a / b;
        Assert.assertThat(c, is(a / b));
    }
}

divisible будет вызываться с любыми комбинациями a и b:

1 / 1
1 / 2
1 / 3
1 / 4
1 / 1
1 / 2
1 / 3
1 / 4
2 / 1
2 / 2
2 / 3
2 / 4
...
4 / 3
4 / 4
4 / 1
4 / 2
4 / 3
4 / 4

Хорошо, не так ли?

Проверьте также мой хэш-код / ​​средство проверки равно .

1 голос
/ 31 июля 2009

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

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

1 голос
/ 31 июля 2009

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

Стремитесь к 100% охвату теста во всех случаях.

1 голос
/ 31 июля 2009

Все зависит от вашего времени и вашего бюджета. В идеальном мире вы должны использовать все возможности. Но мы все знаем, что это немного далеко от реальности.

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

Я бы предложил разделить тестовые наборы по разным категориям и делать все возможное с вашим временем и бюджетом. Постарайтесь охватить основные категории большим количеством тестов, чем вторичными. Это очень важно, потому что обычно 80% времени тратится на 20% кода. И это самая важная часть.

Также важно расставить приоритеты, что необходимо для работы остальных. Допустим, у вас есть приложение, где только подписанные пользователи могут делать вещи. Тогда подписная часть должна быть очень хорошо протестирована, если вы хотите, чтобы ваше приложение было полезным.

Наконец, вы должны попытаться создать несколько приемочных тестов, которые будут указывать, что что-то не так (хотя они не помогут в поиске того, что именно не так).

0 голосов
/ 31 июля 2009

Если вы не можете написать тесты для всего, я бы посоветовал измерить ваше покрытие , используя некоторые инструменты покрытия, такие как cobertura . Это будет по крайней мере гарантировать, что вы покрываете большую часть своего кода, используя некоторое тестирование черного ящика. Измерение охвата очень важно, когда расширяется кодовая база, иначе будет невозможно отследить, насколько хорош ваш набор тестов.

0 голосов
/ 31 июля 2009

С количеством комбинаций, вероятно, нереально охватить все сценарии.

Что вы можете сделать:

  • Проверка всего кода, где это возможно, по крайней мере, один раз (около 100% покрытия кода)

  • Сосредоточьтесь на тех областях, где, по вашему мнению, могут возникнуть проблемы при написании дополнительных тестов.

  • Всякий раз, когда QA обнаруживает ошибку, напишите тест, чтобы показать ошибку, прежде чем ее исправить

0 голосов
/ 31 июля 2009

Написание большого количества модульных тестов с самого первого шага нового приложения - не мой подход. В общем, когда я создаю новое приложение (с нуля), я сначала создаю прототип без UT . Как только у меня есть рабочий прототип сценария солнечного дня, и некоторые коллеги рассматривают его (и утверждают, улучшают и т. Д.) - я делаю две вещи: я пишу модульные тесты, которые охватывают сценарий солнечного дня, и затем реорганизую свой код. 1003 *

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

0 голосов
/ 31 июля 2009

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

Один из подходов заключается в групповых тестовых случаях и нахождении «супер» тестового набора по группам!

Еще один способ - идентифицировать критические модули вашего приложения и управлять его тестовыми примерами в приоритетном порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...