Статьи

Рекомендации по модульному тестированию: Справочное руководство по JUnit

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

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

Разделы в этом посте:

Unit testing is not about finding bugs
Tips for writing great unit tests
Test only one code unit at a time
Don’t make unnecessary assertions
Make each test independent to all the others
Mock out all external services and state
Don’t unit-test configuration settings
Name your unit tests clearly and consistently
Write tests for methods that have the fewest dependencies first, and work your way up
All methods, regardless of visibility, should have appropriate unit tests
Aim for each unit test method to perform exactly one assertion
Create unit tests that target exceptions
Use the most appropriate assertion methods.
Put assertion parameters in the proper order 
Ensure that test code is separated from production code
Do not print anything out in unit tests
Do not use static members in a test class
Do not write your own catch blocks that exist only to fail a test
Do not rely on indirect testing
Integrate Testcases with build script
Do not skip unit tests
Capture results using the XML formatter
Conclusion

В программировании « модульное тестирование — это метод, с помощью которого отдельные блоки исходного кода тестируются, чтобы определить, пригодны ли они для использования». Теперь этот блок исходного кода может очень по разным сценариям.
Например: в процедурном программировании единица может быть целым модулем, но чаще это отдельная функция или процедура. В объектно-ориентированном программировании единица часто представляет собой целый интерфейс, такой как класс, но может быть отдельным методом. Интуитивно следует рассматривать единицу как наименьшую тестируемую часть приложения.

Модульное тестирование — это не поиск ошибок

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

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

«По сути, модульное тестирование должно рассматриваться как часть процесса проектирования, как и в TDD ( Test Driven Development )». Это следует использовать для поддержки процесса проектирования, чтобы разработчик мог идентифицировать каждый наименьший модуль в системе и тестировать его отдельно.

Советы по написанию отличных юнит-тестов

Тестируйте только одну кодовую единицу за раз

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

  1. Первый параметр может быть нулевым. Должно выдать недопустимое исключение параметра.
  2. Второй параметр может быть нулевым. Должно выдать недопустимое исключение параметра.
  3. Оба могут быть нулевыми. Должно выдать недопустимое исключение параметра.
  4. Наконец, проверьте действительный вывод функции. Он должен вернуть действительный предопределенный вывод.

This helps when you do some code changes or do refactoring then to test that functionality has not broken, running the test cases should be enough. Also, if you change any behavior then you need to change single or least number of test cases.

Don’t make unnecessary assertions

Remember, unit tests are a design specification of how a certain behavior should work, not a list of observations of everything the code happens to do.

Do not try to Assert everything just focus on what you are testing otherwise you will end up having multiple testcases failures for a single reason, which does not help in achieving anything.

Make each test independent to all the others

Do not make chain of unit test cases. It will prevent you to identify the root cause of test case failures and you will have to debug the code. Also, it creates dependency, means if you have to change one test case then you need to make changes in multiple testcases unnecessarily.

Try to use @Before and @After methods to setup per-requisites if any for all your test cases. If you need to multiple things to support different test cases in @Before or @After, then consider creating new Test class.

Mock out all external services and state

Otherwise, behavior in those external services overlaps multiple tests, and state data means that different unit tests can influence each other’s outcome. You’ve definitely taken a wrong turn if you have to run your tests in a specific order, or if they only work when your database or network connection is active.

Also, this is important because you would not love to debug the test cases which are actually failing due to bugs in some external system.

(By the way, sometimes your architecture might mean your code touches static variables during unit tests. Avoid this if you can, but if you can’t, at least make sure each test resets the relevant statics to a known state before it runs.)

Don’t unit-test configuration settings

By definition, your configuration settings aren’t part of any unit of code (that’s why you extracted the setting out in some properties file). Even if you could write a unit test that inspects your configuration, then write only single or two test cases for verifying that configuration loading code is working and that’s all.

Testing all your configuration settings in each separate test cases proves only one thing: “You know how to copy and paste.”

Visit the original source for complete guidelines

Happy Learning !!