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


Интересна Java? Кликай по ссылке и изучай!
Если тебе полезно что-то из того, чем я делюсь в своем блоге - можешь поделиться своими деньгами со мной.
с пожеланием
столько времени читатели провели на блоге - 
сейчас онлайн - 

воскресенье, 10 марта 2013 г.

JUnit хитрости: Ассертим все и сразу

Вот как часто пишут пользовательсвие ассерты.
    @Test
    public void test() {
        snake = new Snake(50, 50);

        assertHeadAntTail(50, 50, Direction.RIGHT, Direction.LEFT);
    }

    private void assertHeadAntTail(int x, int y, Direction headDirection, Direction tailDirection) {
        assertEquals(headDirection, snake.getDirection());
        assertEquals(tailDirection, snake.getTailDirection());
        assertEquals(x, snake.getHead().getX());
        assertEquals(y, snake.getHead().getY());
    }
Их недостаток в том, что если слетает первый, то мы не увидим всей картины - остальные не отработают. Этот антипаттерн юнит-тестирования называется "Заяц" - обычно чтобы не писать несколько разных тестов, мы просто подселяем к существующему тесту еще один ассерт. Кстати тут пахнет даже имя метода - assertHeadAndTail :) но проигнорим на минутку этот запах.
Можно изворачиваться так, как я это делал раньше. Но сегодня придумался другой способ, более легковестный.
    @Test
    public void test() {
        snake = new Snake(50, 50);

        assertHeadAntTail(50, 50, Direction.RIGHT, Direction.LEFT);
    }

    private void assertHeadAntTail(int x, int y, Direction headDirection, Direction tailDirection) {
        assertEquals( "[headX, headY, headDirection, tailDirection]",
                asString(x, y, headDirection, tailDirection),

                asString(snake.getHead().getX(), snake.getHead().getY(),
                        snake.getDirection(), snake.getTailDirection()));
    }

    private String asString(Object...args) {
        return Arrays.asList(args).toString();
    }
Слетает так
junit.framework.ComparisonFailure: [headX, headY, headDirection, tailDirection] 
Expected :[50, 50, RIGHT, LEFT]
Actual   :[50, 50, RIGHT, DOWN]
 at com.codenjoy.dojo.snake.model.SnakeDirectionTest.assertHeadAntTail(SnakeDirectionTest.java:72)
 at com.codenjoy.dojo.snake.model.SnakeDirectionTest.test(SnakeDirectionTest.java:36)
Меня устраивает!
Вот если бы только можно было бы находясь в методе получить список его параметров в текстовом виде, чтобы не писать вот так "[headX, headY, headDirection, tailDirection]" в каждом новом ассерте - было бы вообще идеально. Но эту головоломку остави на потом...

1 комментарий:

  1. Я думаю с помощью рефлексии можно так сделать, но мне это не нравится.

    Есть в junit Fluent-assertations как в его потомке nunit (порт junit в .NET), к примеру можно так

    Assert.That(obj, Has.Property("Name").EqualTo("name")
    .And.Property("OtherProperty").GreaterThan(1));

    PS: ты читал Мессароша "xUnit test patterns"?

    ОтветитьУдалить