Интеграционные тесты и TDD - PullRequest
1 голос
/ 13 августа 2010

У меня есть первый тест интеграции для игры в крестики-нолики:

[TestClass]
public class FirstIntegrationTest
{
    [TestMethod, TestCategory("Integration Tests")]
    public void Standard_TicTacToe_Game_PlayerO_Wins()
    {
        IPlayer playerO = new Player();
        IPlayer playerX = new Player();

        Game game = new Game(playerO, playerX);
        game.Start();

        playerO.Play(new Point(0, 0));
        playerX.Play(new Point(2, 2));
        playerO.Play(new Point(1, 0));
        playerX.Play(new Point(1, 2));
        playerO.Play(new Point(2, 0));

        Assert.IsTrue(game.IsOver);
        Assert.IsTrue(playerO.HasWon);
        Assert.IsFalse(playerX.HasWon);
    }
}

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

При проведении интеграционных тестов (а я полагаю, что это интеграционный тест) какой тип юнит-тестов мне следует делать? Должен ли я просто сделать минимум, чтобы пройти тест интеграции? Если это так, мне нужно было бы только установить для класса Game его первый IPlayer HasWon, равный true, а второй - false. Какой смысл вообще заниматься модульным тестированием, если я веду свой дизайн интеграционными тестами?

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

Ответы [ 6 ]

2 голосов
/ 13 августа 2010

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

Здесь у вас есть приемочный тест высокого уровня.

Возможные юнит-тесты:

  • убедитесь, что игроки могут поочередно только по очереди
  • убедитесь, что игроки не могут одновременно отметить координаты
  • убедитесь, что выигрыши по вертикали, диагонали и по горизонтали распознаются (здесь можно проверить все 8 возможностей)
2 голосов
/ 13 августа 2010

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

Интеграционный тест будет содержать больше тестов, касающихся интерфейсов между модулями (csci).

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

Так что да, у вас будет много других методов, охватываемых юнит-тестами.

Пример модульного теста конструктора класса Game:

   IPlayer playerO = new Player();
   IPlayer player1 = new Player();
   IPlayer player2 = new AnotherImplOfIPlayer();

   Game game0 = new Game(player0, player1);   // this should work
   Game game1 = new Game(player0, player2);   // this should work
   Game game2 = new Game(null, null);         // exception thrown?    
   Game game3 = new Game(player0, player0);   // exception thrown?

A unit test проверяет правильность единицы компиляции. Вы наложили некоторые требования на модуль компиляции (написанные или запомнились) и проверили эти требования. Полностью независим от функциональности вышестоящего приложения. Зачем? Потому что вы можете захотеть повторно использовать модуль компиляции в других проектах и ​​хотите быть уверены, что этот модуль компиляции не содержит ошибок (в отношении спецификации модуля).

A BVT проверяет, был ли процесс сборки корректным и завершенным. Он проверяет, создало ли оно исполняемое приложение.

Функциональный тест

A предназначен для функциональных требований для полного применения. Многие функциональные тесты не являются автоматическими, а выполняются с помощью письменных тестовых сценариев и выполняются тестировщиками.

1 голос
/ 13 августа 2010

Разница между модульным тестом и интеграционным тестом очень субъективна.

Кто-то скажет, что это интеграционный тест, когда вы объединяете более одной единицы (как вы здесь).Другие скажут, что для того, чтобы быть интеграционным тестом, нужно прикоснуться к некоторому компоненту вне вашего контроля в среде (например, к базе данных или внешнему API).

Хотя я предпочитаю последнее определение, аргумент может быть приведен для каждого.И даже тогда, действительно ли это действительно имеет значение в действительности?Это полезный тест, он быстрый и более стабильный, чем интеграционный тест.По этой причине я бы сгруппировал его с юнит-тестами в моем локальном и CI-тестировании.

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

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

1 голос
/ 13 августа 2010

Проблема с ответом на ваш вопрос заключается в том, что он субъективен, и мы не знаем ваше приложение, как вы.

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

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

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

По моему опыту, модульные тесты короче писать и могут копать глубже с меньшими усилиями. Вот почему я предпочитаю их. Я пишу меньше интеграционных тестов (тесты, которые охватывают основные пути, и я склонен использовать их в качестве BVT), и еще меньше "сквозных" тестов (если у меня несколько пар приложений / клиентских серверов, полных процессов и т. Д. Для тестирования ).

1 голос
/ 13 августа 2010

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

public void cannotPlaySameMovementTwice() {
    playerO.Play(new Point(0, 0));
    playerX.Play(new Point(0, 0));
    // You should assert some exception result here
}
0 голосов
/ 13 августа 2010

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

Этот конкретный тест не может пройти, пока вы не создадите интерфейс, три класса и как минимум четыре метода. Так что я бы не назвал это тест-драйвом.

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