Как строгий должен, я быть в “делаю самую простую вещь, которая могла возможная работа” при выполнении TDD

Для TDD Вы имеете к

  1. Создайте тест тот сбой
  2. Сделайте самую простую вещь, которая могла возможная работа, чтобы пройти тест
  3. Добавьте больше вариантов теста и повторения
  4. Осуществите рефакторинг, когда шаблон появится

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

Например, я обрабатываю файл и если он не соответствует определенному формату, я должен бросить InvalidFormatException

Таким образом, мой первый тест был:

@Test 
void testFormat(){
    // empty doesn't do anything nor throw anything
    processor.validate("empty.txt"); 
    try {
        processor.validate("invalid.txt");
        assert false: "Should have thrown InvalidFormatException";
    } catch( InvalidFormatException ife ) {
        assert "Invalid format".equals( ife.getMessage() );
    }
 }

Я выполняю его, и это перестало работать, потому что это не выдает исключение.

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

public void validate( String fileName ) throws InvalidFormatException {
    if(fileName.equals("invalid.txt") {
        throw new InvalidFormatException("Invalid format");
    }
}

Doh!! (хотя реальный код немного более сложен, я нашел мой сам выполнение чего-то вроде этого несколько раз),

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

Q: я беру слишком литеральный, "Делают самую простую вещь..." материал?

17
задан John Saunders 10 June 2010 в 14:08
поделиться

6 ответов

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

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

7
ответ дан 30 November 2019 в 13:45
поделиться

Конечно, ваша интерпретация правила слишком буквальна. Возможно, оно должно звучать так: "Сделай самую простую потенциально полезную вещь..."

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

3
ответ дан 30 November 2019 в 13:45
поделиться

Много комментариев:

  • Если при проверке "empty.txt" возникает исключение, вы его не ловите.

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

  • Я не вижу никаких признаков фреймворка для юнит-тестирования. Может быть, я их упускаю? Но простое использование assert не позволит масштабировать большие системы. Когда вы получаете результат от проверки, у вас должен быть способ сообщить системе тестирования, что данный тест с данным именем прошел успешно или не прошел.

  • Меня настораживает идея, что проверка имени файла (в отличие от содержимого) представляет собой "валидацию". На мой взгляд, это немного слишком просто.

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

2
ответ дан 30 November 2019 в 13:45
поделиться

Как метод должен делать только одну вещь, один тест должен проверять только одну вещь (поведение). Для примера я бы написал два теста, например, test_no_exception_for_empty_file и test_exception_for_invalid_file. Во втором случае может быть несколько тестов - по одному на каждый вид недействительности.

Третий шаг процесса TDD должен интерпретироваться как "добавить новый вариант теста", а не "добавить новый вариант к тесту". Действительно, модульный тест должен быть атомарным (тестировать только одну вещь) и обычно следует шаблону тройки А: Arrange - Act - Assert. И очень важно сначала проверить, что тест не сработал, чтобы убедиться, что он действительно что-то тестирует.

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

1
ответ дан 30 November 2019 в 13:45
поделиться

Я тоже новичок в TDD, который борется с этим вопросом. В процессе поиска я нашел эту запись в блоге Роя Ошерова, которая была первым и единственным конкретным и осязаемым определением "самой простой вещи, которая может работать", которое я нашел (и даже Рой признал, что это только начало).

В двух словах, Рой говорит:

Посмотрите на код, который вы только что написали, в вашем производственном коде и спросите себя:

"Могу ли я реализовать то же самое решение способом, который ..."

  1. "... Более жестко закодирован..."
  2. "... Ближе к началу метода, в котором я его написал.... "
  3. ".. Меньше отступов (как можно меньше "диапазонов", таких как ifs, loops, try-catch) ..."
  4. "... короче (буквально меньше символов для написания), но все еще читабельно ..."

"... и все еще заставляет все тесты проходить?"

Если ответ на один из этих вопросов "да", то сделайте это, и увидите, что все тесты все еще проходят.

3
ответ дан 30 November 2019 в 13:45
поделиться

Вы пропустили пункт #0 в вашем списке: знать, что делать. Вы говорите, что обрабатываете файл в целях проверки. Как только вы определите, что означает "валидация" (подсказка: сделайте это до написания кода), вы сможете лучше понять, как а) писать тесты, которые, ну, проверяют спецификацию как реализованную, и б) писать простейшие вещи.

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

2
ответ дан 30 November 2019 в 13:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: