Модульное тестирование, достоинства и недостатки, инструментарий

Лекция



Привет, Вы узнаете о том , что такое модульное тестирование, Разберем основные их виды и особенности использования. Еще будет много подробных примеров и описаний. Для того чтобы лучше понимать что такое модульное тестирование, tdd, unit testing, блочное тестирование , настоятельно рекомендую прочитать все из категории Разработка программного обеспечения и информационных систем.

модульное тестирование , иногда блочное тестирование или юнит-тестирование (англ. unit testing) — процесс в программировании, позволяющий проверить на корректность отдельные модули исходного кода программы, наборы из одного или более программных модулей вместе с соответствующими управляющими данными, процедурами использования и обработки.

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

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

Этот тип тестирования обычно выполняется программистами.

Определение Unit Testing


Модульное тестирование — метод повышения качества ПО при котором отдельные участки программного кода (классы, методы, функции)
тестируются на предмет адекватности поведения (отсутствие ошибок, исключения, корректные выходные параметры).


Модульное тестирование — пример автоматизированного тестирования методом белого ящика.
Модульное тестирование — пример регрессионного тестирования.
Модульное тестирование проводится разработчиками (разработка и запуск тестов).

Почему модульного тестирования важно

  • Код имеет более высокое качество с самого начала
  • Меньше ошибок
  • Самоописание кода, документирование
  • Снижение стоимости исправлении ошибок по их устранению ранее, чем позже
  • Безопасный дальнейший рефакторинг

При этом создается код с максимально чистой функцией (методами) , для того чтобы тесты былиь изолированы от окружения (БД, сеть, файловая система, время).

Применение Unit Testing

разрабатывается участок программного кода (как правило новый метод или класс ).

public class Sort {
private void swap(int[] arr, int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
public void bubblesort( int[] arr ){
for(int i = arr.length-1 ; i >= 0 ; i--){
for(int j = 0 ; j < i ; j++){
if( arr[j] > arr[j+1] )
swap(arr, j, j+1);
}
}
}
}


Размер кода должен быть сравнительно небольшой. Для таких участков легче разрабатывать модульные тесты
● Присутствие входных/выходных параметров

Для участка разрабатывается несколько модульных тестов, так чтобы были покрыты все условия и циклы,

а также комбинация различных входных выходных параметров

public class SortTestCase extends TestCase {
public void testSwap{
int[] i={1,2};
Sort sorter = new Sort();
sorter.swap(i,0,1);
AssertEquals(2, i );
AssertEquals(1, i );
}
public void testSortWithOrdinaryData(){
int[] i=new int {4,1,2};
Sort sorter = new Sort();
sorter.bubblesort(i);
AssertEquals(new int {1,2,4}, i);
}
public void testSortWithSOrtedData(){
int[] i=new int {1,2,4};
Sort sorter = new Sort();
sorter.bubblesort(i);
AssertEquals(new int {1,2,4}, i);
}
public void testSortWithEmptyData(){
int[] i=new int ;
Sort sorter = new Sort();
sorter.bubblesort(i);
AssertEquals(new int , i);
}
}

Запуск модульных тестов Через консоль

Запуск

Модульное тестирование, достоинства и недостатки, инструментарий

Получение результатов

Модульное тестирование, достоинства и недостатки, инструментарий

Запуск модульных тестов

Через среду разработки (Eclipse, NetBeans,Idea PhpShtorm .

Модульное тестирование, достоинства и недостатки, инструментарий

Лучшие практики

  • Программный код должен быть разбит на небольшие участки с хорошо изолированными входными и выходными параметрами
  • Разработка тестов в паре с программным кодом
  • Избегание явного создания объектов внутри программного кода. Вместо этого использовать паттерн Factory, а также Dependency Injection Frameworks.
  • Избегайте использования глобальных переменных.
  • Обеспечение как можно более высокого покрытия тестами.
  • Структурирование тестов по тесткейсам. Каждый тестирующий метод должен иметь понятное имя.
  • Накопление тестов (Регрессия)
  • Запуск тестов после каждого изменения в программном коде, а также перед commit в репозиторий.
  • Правило 3А (Arrange — Act — Assert)
  • Для управления зависимостями использовать Mock frameworks.
  • исползуйте максимално чистые функции (методами) , для того чтобы тесты былиь изолированы от окружения (БД, сеть, файловая система, время).

Достоинства и ограничения модульных тестов

Достоинства

  • Раннее обнаружение дефектов
  • Возможность рефакторинга кода на поздних стадиях проекта
  • Раннее обнаружение архитектурных изъянов в интерфейсах и работе системы
  • Документация. Модульные тесты — своего рода примеры использования кода.

Поощрение изменений

Модульное тестирование позже позволяет программистам проводить рефакторинг, будучи уверенными, что модуль по-прежнему работает корректно (регрессионное тестирование). Об этом говорит сайт https://intellect.icu . Это поощряет программистов к изменениям кода, поскольку достаточно легко проверить, что код работает и после изменений.

Упрощение интеграции

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

Документирование кода

Модульные тесты можно рассматривать как «живой документ» для тестируемого класса. Клиенты, которые не знают, как использовать данный класс, могут использовать юнит-тест в качестве примера.

Отделение интерфейса от реализации

Поскольку некоторые классы могут использовать другие классы, тестирование отдельного класса часто распространяется на связанные с ним. Например, класс пользуется базой данных; в ходе написания теста программист обнаруживает, что тесту приходится взаимодействовать с базой. Это ошибка, поскольку тест не должен выходить за границу класса. В результате разработчик абстрагируется от соединения с базой данных и реализует этот интерфейс, используя свой собственный mock-объект. Это приводит к менее связанному коду, минимизируя зависимости в системе.

Ограничения и недостатки

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

Модульное тестирование не Грааль и не позволяет отловить 100% дефектов (out of scope: integration tests, UI tests, load and stress tests).

Сложный код

Тестирование программного обеспечения — комбинаторная задача. Например, каждое возможное значение булевской переменной потребует двух тестов: один на вариант TRUE, другой — на вариант FALSE. В результате на каждую строку исходного кода потребуется 3−5 строк тестового кода.

Алгоритмы вроде Marching cubes или красно-черного дерева имеют разветвленное дерево решений, и чтобы проверить все варианты, нужны огромные наборы тестов .

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

Результат известен лишь приблизительно

Например, в математическом моделировании. Бизнес-приложения зачастую работают с конечными и счетными множествами, научные — с континуальными. Поэтому сложно подобрать тесты для каждой из ветвей программы, сложно сказать, верен ли результат, выдерживается ли точность, и т. д. А во многих случаях качество моделирования определяется «на глаз», и последний результат записывается как «опорный». Если найдено расхождение, новый результат проверяют вручную и выясняют, какой качественнее: старый или новый.

Код, взаимодействующий с системой

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

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

Ошибки интеграции и производительности

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

При общей низкой культуре программирования

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

Проблемы с объектами-заглушками

За исключением простейших случаев, тестируемый объект должен взаимодействовать с другими объектами. Этих «товарищей по взаимодействию» — объекты-заглушки — делают предельно простыми: либо крайне упрощенными (память вместо базы данных), либо рассчитанными на конкретный тест и механически повторяющими сессию обмена. Проблемы могут возникать при смене протокола обмена, в таком случае объекты-заглушки должны отвечать новым требованиям протокола.

TDD — Test Driven Development

Модульное тестирование, достоинства и недостатки, инструментарий

Еще о TDD

Два вида написания тестов при TDD

В самом начале тестами реализуется спецификации поведения будущего класса через входы выходы.

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

Особенности TDD

Использование TDD предпочтительно там, где интерфейсы классов хорошо определены.

В случае нестабильных интерфейсов, сначала необходимо довести их до «ума», после чего можно реализовывать тесты.

Advanced Unit tests

  • Обработка exceptions
  • Метод не имеет явных выходных параметров
  • Управление зависимостями
  • Работа с БД и сетью
  • Интеграционные тесты

Обработка исключений

public class DataBaseReaderTestCase extends TestCase{

@Test(expected=UnauthorizedException.class) public voidtestUnauthorizedAccess(){

DatabaseReader reader = new DatabaseReaderImpl(); reader.getUsersCount();

}

}

Две точки зрения на покрытие методов класса

  • Параноидальная - Все методы, включая приватные, должны быть покрыты тестами, при этом все вызываемые приватные методы должны быть изолированы (partial mocking + slims)
  • Прагматичная - Все публичные и приватные методы должны быть покрыты тестами. При этом вызываемые методы не изолируются ,а остаются as is. Для данных методов пишутся отдельные тесты.

Инструментарий для модульного тестирования

Для большинства популярных языков программирования высокого уровня существуют инструменты и библиотеки модульного тестирования. Некоторые из них:

  • Для ActionScript 2.0 — язык сценариев, используемый виртуальной машиной Adobe Flash Player версии 7 и 8
    • AsUnit
    • AS2Unit
  • Для ActionScript 3.0 — скриптовый язык, используемый виртуальной машиной Adobe Flash Player версии 9 и выше
    • FlexUnit
    • AsUnit
  • Для C
    • CUnit cunit
    • CTESK UniTESK.ru
    • cfix cfix
    • API Sanity Autotest — для динамических C/C++ библиотек в Unix-подобных ОС.
    • Unity unity — для встраиваемых приложений
    • MICRO UNIT MICRO_UNIT — небольшой набор макросов с примерами использования.
  • Для Ruby
    • Rspec
    • Test::Unit
  • Для Objective-C
    • OCUnit
  • Для C++
    • TypeMock Isolator++ за C++ и Isolator за .NET
    • CxxTest
    • CPPUnit [10]
    • Boost Test [11]
    • Google C++ Testing Framework [12]
    • Symbian[13] — фреймворк для Symbian OS всех версий.
    • API Sanity Autotest — для динамических C/C++ библиотек в Unix-подобных ОС.
    • Qt Test framework — для программ, разработанных с помощью библиотеки Qt
  • Для C#
    • TypeMock Isolator за C# [14]
    • Nunit [15]
    • XUnit.net [16]
    • MbUnit [17]
  • Для Delphi
    • DUnit [18]
    • DUnitX [19]
  • EUnit [20] — Erlang
  • Для Java и Groovy
    • JUnit JUnit.org
    • TestNG testNG.org
    • JavaTESK UniTESK.ru
    • Spock[en] (написан на Groovy)
  • Для JavaScript
    • Mocha (тестовый фреймворк) [21]
    • Jest [22]
    • Chai («assertion library», используется совместно с тестовым framework’ом) [23]
    • Sinon.JS (библиотека для создания mock’ов, stub’ов, spy’ев, используется совместно с тестовым framework’ом) [24]
    • Karma runner (от создателей Angular.JS, «test runner» — организует среду выполнения тестов) [25]
    • QUnit (от создателей jQuery) [26]
    • JsUnit (больше не поддерживается создателями) [27]
    • Jasmine (рекомендован создателями jsUnit) [28]
    • D.O.H [29]
  • Для Perl
    • Test [30]
    • Test::Simple [31]
    • Test::More [32]
    • Test::Unit [33]
    • Test::Unit::Lite [34]
  • Для PHP
    • SimpleTest
    • PHPUnit [35]
  • Для Python
    • PyUnit [36]
    • PyTest [37]
    • Nose [38]
  • vbUnit [39] — Visual Basic
  • utPLSQL [40] — PL/SQL
  • Для T-SQL
    • TSQLUnit [41]
    • SPUnit [42]

Поддержка на уровне языка

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

Пример таких языков:

  • Cobra
  • D

Пример кода на языке D

class ABC
{
    this() { val = 2; }

    private int val;
    public func() { val *= 2; }
}

unittest
{
   ABC a;
   a.func();

   assert( a.val > 0 && a.val < 555 ); // можно обратиться к приватной переменной внутри модуля
}

Вау!! 😲 Ты еще не читал? Это зря!

В заключение, эта статья об модульное тестирование подчеркивает важность того что вы тут, расширяете ваше сознание, знания, навыки и умения. Надеюсь, что теперь ты понял что такое модульное тестирование, tdd, unit testing, блочное тестирование и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Разработка программного обеспечения и информационных систем

создано: 2016-01-18
обновлено: 2024-11-13
182



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей

Комментарии


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

Разработка программного обеспечения и информационных систем

Термины: Разработка программного обеспечения и информационных систем