1 чем отличаются юнит тестирование от компонентного

Раздел: тестирование gt; уровни тестирования gt; компонентное или модульное тестирование компонентное модульное тестирование проверяет функциональность и ищет дефекты в частях

Раздел: Тестирование > Уровни Тестирования > Компонентное или Модульное тестирование

Компонентное (модульное) тестирование проверяет функциональность и ищет дефекты в частях приложения, которые доступны и могут быть протестированы по-отдельности (модули программ, объекты, классы, функции и т.д.). Обычно компонентное (модульное) тестирование проводится вызывая код, который необходимо проверить и при поддержке сред разработки, таких как фреймворки (frameworks — каркасы) для модульного тестирования или инструменты для отладки. Все найденные дефекты, как правило исправляются в коде без формального их описания в системе менеджмента багов (Bug Tracking System).

Один из наиболее эффективных подходов к компонентному (модульному) тестированию — это подготовка автоматизированных тестов до начала основного кодирования (разработки) программного обеспечения. Это называется разработка от тестирования (test-driven development) или подход тестирования вначале (test first approach). При этом подходе создаются и интегрируются небольшие куски кода, напротив которых запускаются тесты, написанные до начала кодирования. Разработка ведется до тех пор пока все тесты не будут успешно пройдены.

Разница между компонентным и модульным тестированием

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

Наверх

Компонентное
(модульное) тестирование проверяет
функциональность и ищет дефекты в частях
приложения
, которые
доступны и могут быть протестированы
по-отдельности (модули
программ, объекты, классы, функции и
т.д.
). Обычно
компонентное (модульное) тестирование
проводится вызывая код, который необходимо
проверить и при поддержке сред разработки,
таких как фреймворки (frameworks — каркасы)
для модульного тестирования или
инструменты для отладки. Все найденные
дефекты,
как правило исправляются в коде без
формального их описания в системе
менеджмента багов (Bug Tracking System).

Один
из наиболее эффективных подходов к
компонентному (модульному) тестированию
— это подготовка
автоматизированных тестов

до начала основного кодирования
(разработки) программного обеспечения.
Это называется разработка от тестирования
(test-driven development)
или подход тестирования вначале (test
first approach
). При этом
подходе создаются и интегрируются
небольшие куски кода, напротив которых
запускаются тесты, написанные до начала
кодирования. Разработка ведется до тех
пор пока все тесты не будут успешными.

Разница между компонентным и модульным тестированием

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

Интеграционное тестирование (Integration Testing)

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

Уровни интеграционного тестирования:

  • Компонентный
    интеграционный уровень

    (Component
    Integration testing
    )

Проверяется
взаимодействие между компонентами
системы после проведения компонентного
тестирования.

  • Системный
    интеграционный уровень

    (System
    Integration Testing
    )

Проверяется
взаимодействие между разными системами
после проведения системного тестирования.

Подходы к интеграционному тестированию:

  • Снизу
    вверх
    (Bottom
    Up Integration
    )

Все
низкоуровневые модули, процедуры или
функции собираются воедино и затем
тестируются. После чего собирается
следующий уровень модулей для проведения
интеграционного тестирования. Данный
подход считается полезным, если все или
практически все модули, разрабатываемого
уровня, готовы. Также данный подход
помогает определить по результатам
тестирования уровень готовности
приложения (см. также Integration
testing — Bottom Up)

  • Сверху
    вниз
    (Top
    Down Integration
    )

Вначале
тестируются все высокоуровневые модули,
и постепенно один за другим добавляются
низкоуровневые. Все модули более низкого
уровня симулируются заглушками с
аналогичной функциональностью, зачем
по мере готовности они заменяются
реальными активными компонентами. Таким
образом мы проводим тестирование сверху
вниз. (см. также Top
Down Integration)

  • Большой
    взрыв
    («Big
    Bang» Integration
    )

Все
или практически все разработанные
модули собираются вместе в виде
законченной системы или ее основной
части, и затем проводится интеграционное
тестирование. Такой подход очень хорош
для сохранения времени. Однако если
тест кейсы и их результаты записаны не
верно, то сам процесс интеграции сильно
осложнится, что станет преградой для
команды тестирования при достижении
основной цели интеграционного тестирования
(см. также Integration
testing — Big Bang)

Системное
тестирование (System Testing)

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

Можно
выделить два подхода к системному
тестированию:

  • на
    базе требований

    (requirements
    based
    )

Для
каждого требования пишутся тестовые
случаи (test cases), проверяющие выполнение
данного требования.

  • на
    базе случаев использования

    (use
    case based
    )

На
основе представления о способах
использования продукта создаются случаи
использования системы (Use
Cases
).
По конкретному случаю использования
можно определить один или более сценариев.
На проверку каждого сценария пишутся
тест
кейсы (test cases), которые должны быть
протестированы.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

В продолжение статьи о КОП я подробней расскажу о тестировании компонентов.
Существует много информации о юнит-тестировании и BDD, эта статья будет посвящена настройке SpecFlow для работы с Unity Engine, а также содержать общие рекомендации по созданию тестируемой архитектуры игры с компонентно-ориентированным подходом.

Общие правила разработки компонента, который можно будет легко протестировать, я сформулировал так:
1) То, что может видеть/слышать только человек, должно быть в отдельном компоненте.
2) У компонента должно быть «дефолтное» поведение. Лучше считать его эталонным.
3) Не забывайте: один компонент — одно поведение.
Таким образом, я внёс корректировки в свою реализацию core gameplay игры жанра Tower Defense:
Некоторые компоненты обращаются к Renderer через GetComponent() —это ненужная зависимость от обязательного присутствия компонента Renderer. Вся визуализация должна быть в отдельных компонентах. Указал дефолтные значения всем полям: это упростит и саму настройку компонента. Также расширил функционал игры, введя Игрока:
Игрок — человек, чьё поведение состоит в передаче управления в игру, посредством устройств ввода.
Теперь, для начала игры, надо нажать кнопку «Начать игру» в UI, после чего выбрать в UI башни для постройки с указанием куда их построить. И когда все башни будут построены, начнётся игра.
Но вот вопрос: для каких компонентов нужны Unit тесты, а какие лучше проверять по спецификации?
Ответ на этот вопрос может быть разным в зависимости от количества компонентов и общей сложности проекта. Стоит помнить, что общее поведение игрового объекта складывается из поведений компонентов. И рекомендация у меня такая:
Необходимо оценить сложность реализации логики внутри компонента. Если в ней легко допустить ошибку, стоит подстраховаться и сделать отдельный юнит-тест для компонента. В других случаях можно сделать общую спецификацию, которая будет проверять поведение игрового объекта в целом.
Подготовительная работа.
Из дополнений к Unity, нам понадобится следующее:
1) UnityTestTools — runner NUnit-тестов от разработчиков Unity в среде редактора.
2) Visual Studio Tools (бывший UnityVS) — плагин для отладки.
Для Visual Studio понадобится SpecFlow
И начнём мы с Unit-тестов.
Многие добавляют юнит-тесты непосредственно в сам проект, но не стоит утяжелять сборку лишним. Не так много времени займёт выделение набора тестов в отдельную сборку, которая не будет включена в финальную версию игры (build).
После добавления UnityTestTools в Unity, нужно открыть решение (сгенерированное UnityVs) и добавить в него новый проект типа «библиотека классов», в ней и будут наши юнит-тесты компонентов. Для примера, назовём сборку TowerDefenseCore.UnitTests. Важным моментом является настройка сборки:
1) В references сборки надо добавить:
— «nunit.framework.dll» и «nunit.core.dll» из AssetsUnityTestToolsUnitTestingEditorNUnitLibs
— «UnityEngine.dll» из LibraryUnityAssemblies
— Сборку «Assembly-CSharp.dll» из решения

Важно:

не надо их копировать локально.
2) Необходимо настроить свойства сборки, указав путь вывода. Сборка должна быть в директории Assets — например, AssetsTests.
Написание юнит-тестов, исполняемых в Unity Test Runner, ничем не отличается от обычных юнит-тестов. Однако, есть несколько важных моментов.
Первое: делать инстанциирование игрового объекта (метод GameObject.Instantiate) не обязательно.
Вот простой тест компонента DamageApplicator:

[Test]
public void DamageApplicator_DirectDamage()
{
        var damageApplicator = new DamageApplicator();
        var hp = damageApplicator.DirectDamage(100, 10);
        Assert.AreEqual(90f, hp);
}

DamageApplicator не имеет никаких зависимостей от других компонентов, которые разрешались бы в методе Awake/Start/OnEnable. Но если компонент использует Awake с этой целью, то его нужно вызывать принудительно:

[Test]
public void Hittable_DeadOnDirectDamage()
{
        var componentsHolder = new GameObject();
	    //Добавляем компонент, от которого зависит тестируемый компонент
        componentsHolder.AddComponent<DamageAplicator>();
        var hittable = componentsHolder.AddComponent<Hittable>();
        hittable.Awake();//Важно: мы не сделали инстанс объекта, потому вручную внедрим зависимость от DamageApplicator
			
        hittable.DirectDamage(50);
        Assert.AreEqual(50, hittable.HP);
        hittable.DirectDamage(50);
        Assert.AreEqual(true, hittable.IsDead);
}

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

[Test]
[MaxTime(10000)]//BeginDPS наносит 5 единиц урона каждый 0.5 сек, у цели 100HP
public void DamageInflictor_BeginDPS()
{
        var target = new GameObject();
        target.AddComponent<DamageApplicator>();
        var hittable = target.AddComponent<Hittable>();
        hittable.Awake();
        var tower = new GameObject();
        var dmger = tower.AddComponent<DamageInflictor>();
        dmger.BeginDPS(hittable);//Запускаем Coroutine        
        while (dmger.inflictDamage().MoveNext())//Симулируем работу Coroutine
                Thread.Sleep(100);
        Assert.True(hittable.IsDead);
}

Третий момент: лучше тестировать поведение каждого компонента, а не сцены в целом. В настройках Test Runner в опциях укажите Run test on a new scene.
Соберём сборку, переключимся на Unity и в меню Unity Test Tools выберем Test Runner. Как увидите, тесты из сборки появятся для запуска.

Настройка SpecFlow.
Создадим библиотеку классов TowerDefenseCore.Specs в решении. Настроим её:
1) Добавим в неё пакеты: Install-Package SpecFlow.NUnit
2) Добавим зависимости сборки:
— «TechTalk.SpecFlow.dll» из packagesSpecFlow.1.9.0libnet35
— «UnityEngine.dll» из LibraryUnityAssemblies
— Сборку «Assembly-CSharp.dll» из решения

Важно:

не надо их копировать локально.
3) Необходимо настроить свойства сборки, указав путь вывода. Сборка должна быть в директории Assets — например AssetsTests.
4)

Важно:

скопируем «TechTalk.SpecFlow.dll» в AssetsUnityTestToolsUnitTestingEditorNUnitLibs.
Теперь в Test Runner помимо тестов из TowerDefenseCore.UnitTests будут и Steps из TowerDefenseCore.Specs.

Простой пример Feature, проверяющий поведение крипа при получении урона:
Feature: CreepLogic
Creep alive, take damage and dead.
@ creep
Scenario: Check creep is dead
Given Creep is alive
When Creep take damage 100
Then Creep is dead
И сгенерированные шаги:

[Binding]
public class CreepLogicSteps
{
     private Hittable _creep;
     [Given(@"Creep is alive")]
     public void GivenCreepIsAlive()
     {
         var componentsHolder = new GameObject();
         componentsHolder.AddComponent<DamageApplicator>();
         _creep = componentsHolder.AddComponent<Hittable>();
         _creep.Awake();
     }
     [When(@"Creep take damage (.*)")]
     public void WhenCreepTakeDamage(int dmg)
     {
         _creep.DirectDamage(dmg);
     }
     [Then(@"Creep is dead")]
     public void ThenCreepIsDead()
     {
         NUnitFramework.Assert.AreEqual(true, _creep.IsDead);
     }
}

В Test Runner тест будет отображён с названием CheckCreepIsDead.

В начале статьи я упоминал про поведение Игрока. Какие есть способы автоматизировать проверку его поведения без участия человека — тема для отдельной статьи.

Статистика проекта за месяц

Новых пользователей: 2807

Создано вопросов: 17705

Написано ответов: 36898

Начислено баллов репутации: 858339

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

«Юнит-тестирование и интеграционное тестирование — возможно самые применяемые виды тестирования, которым подвергается современный софт.

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

Юнит-тестирование

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

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

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

➖ Челленджи юнит-тестирования

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

➕ Плюсы юнит-тестирования

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

Интеграционное тестирование

В отличие от юнит-тестирования, нацеленного на (небольшие) модули, интеграционное тестирование является в некоем роде противоположностью — оно проверяет весь код и плюс его зависимости. Юниты-модули могут быть сколь угодно идеальными, а приложение в целом будет бесполезным, если весь код «в целом» не работает как положено во внешнем окружении после деплоя. Другими словами, интеграционное тестирование тестирует приложение «во всей его красе».

Интеграционные тесты выполняются QA-отделом (или QA-командой), который выполняет тест-кейсы, проверяя производительность и функциональность приложения.

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

➖ Челенджи в интеграционном тестировании

Хотя интеграционные тесты делаются чтобы проверить связность компонентов «в реальном мире» включая «выходы приложения», бывает не так просто создать “тестовое окружение как в реальном мире”. Всегда есть какие-то ограничения, потому что внешние системы часто сложны в интеграции с тестовым окружением. Хорошая новость: есть подходящие решения для тестировщиков, «приближающие» интеграционные тесты к реальному миру.

➕ Плюсы интеграционного тестирования

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

Какие тесты нужны, юнит- или интеграционные?

Ситуации бывают разные. Теоретически надо применять оба типа, а реально все зависит от требований клиента и бизнес-целей. Обычно делается последовательно: разработчики “пропустили” свой код через юнит-тестирование, затем тестировщики занялись интеграционным тестированием, проверяя функциональность и эффективность всего приложения и его зависимостей.»