Как писать Unit-тесты в Unity? Что такое Test Runner?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Как писать Unit тесты в Unity и что такое Test Runner
Практика Unit-тестирования в Unity является критически важной для создания стабильного, надежного и легко поддерживаемого кода, особенно в долгосрочных проектах. Она позволяет изолировать и проверить функциональность отдельных компонентов системы, минимизируя влияние человеческих ошибок и упрощая рефакторинг.
Test Runner: Центральный инструмент для тестирования в Unity
Test Runner — это интегрированная в Unity Editor (с версии 2017.1) система для создания, управления и запуска тестов. Он предоставляет графический интерфейс (Test Runner Window) и поддерживает два основных типа тестов:
- Edit Mode Tests: Тесты, которые выполняются внутри редактора Unity, без запуска игрового режима (Play Mode). Они идеальны для проверки логики классов, алгоритмов, математических вычислений, систем данных и т.д.
- Play Mode Tests: Тесты, которые запускаются в специальном, временном игровом режиме. Они необходимы для проверки поведения, зависящего от игрового цикла (например,
Update(),Start()), физики (коллайдеры, Rigidbody), взаимодействия сGameObjectиMonoBehaviourкомпонентами.
Test Runner автоматически обнаруживает тестовые классы в проекте, организует их по категориям и позволяет запускать тесты индивидуально, по группам или все сразу. Результаты тестов (прохождение/непрохождение, время выполнения, ошибки) отображаются в том же окне, что делает процесс удобным и централизованным.
Практика написания Unit тестов в Unity
1. Организация проекта и установка Test Framework
Тесты обычно размещаются в отдельной папке проекта, например /Tests. Тестовый фреймворк поставляется с Unity через Package Manager. Для его использования необходимо импортировать пакет Unity Test Framework (ранее известный как NUnit). Тесты пишутся на C#.
2. Структура тестового класса и методы
Тестовые классы помечаются атрибутом [TestFixture], а тестовые методы — [Test]. Для Play Mode тестов дополнительно используется [UnityTest]. Используются стандартные утверждения (Assertions) из фреймворка NUnit.
using UnityEngine;
using UnityEngine.TestTools;
using NUnit.Framework;
// Edit Mode Test пример
[TestFixture]
public class CalculatorTests
{
private Calculator calculator;
[SetUp] // Выполняется перед каждым тестом
public void Setup()
{
calculator = new Calculator();
}
[Test]
public void Add_TwoPositiveNumbers_ReturnsCorrectSum()
{
int result = calculator.Add(5, 3);
Assert.AreEqual(8, result); // Ключевое утверждение (Assert)
}
[Test]
public void Divide_ByZero_ThrowsException()
{
Assert.Throws<System.DivideByZeroException>(() => calculator.Divide(10, 0));
}
}
3. Тестирование MonoBehaviour компонентов (Play Mode)
Для тестирования компонентов Unity, которые зависят от игрового цикла или объектов в сцене, необходимы Play Mode тесты и часто используются вспомогательные методы для создания объектов.
[TestFixture]
public class PlayerMovementTests
{
[UnityTest] // Атрибут для Play Mode теста
public IEnumerator Move_Player_MovesToCorrectPosition()
{
// 1. Создание тестового GameObject и компонента
GameObject playerGO = new GameObject("TestPlayer");
PlayerMovement playerMovement = playerGO.AddComponent<PlayerMovement>();
playerMovement.speed = 5f;
Vector3 startPos = playerGO.transform.position;
Vector3 targetDirection = Vector3.forward;
// 2. Запуск игровой логики и ожидание
playerMovement.Move(targetDirection);
yield return new WaitForSeconds(1.0f); // Используем корутину для ожидания
// 3. Проверка результата
Vector3 expectedPos = startPos + targetDirection * playerMovement.speed * 1.0f;
Assert.AreEqual(expectedPos.x, playerGO.transform.position.x, 0.1f); // Проверка с допустимой погрешностью (delta)
// 4. Очистка (важно для предотвращения утечек ресурсов между тестами)
Object.Destroy(playerGO);
}
}
4. Key Principles и Best Practices
- Изоляция: Каждый тест должен быть независимым. Используйте методы
[SetUp]и[TearDown]для подготовки и очистки общего состояния. - Naming Convention: Имена тестов должны четко описывать что тестируется, при каких условиях и какой ожидается результат (например,
CalculateDamage_WhenArmorIsZero_ReturnsFullDamage). - Assertions: Используйте разнообразные утверждения (
Assert.AreEqual,Assert.IsTrue,Assert.Throws) для точной проверки. - Mocking и Interfaces: Для тестирования классов, зависящих от сложных систем Unity (например,
Input,Physics), или для изоляции от реальных данных, используйте интерфейсы и внедрение зависимостей (DI), создавая мок-объекты в тестах. - Тестирование частных методов: Обычно рекомендуется тестировать только публичный API. Если приватный метод критически важен, его можно либо сделать внутренним (
internal) и использовать атрибут[assembly: InternalsVisibleTo("TestAssembly")], либо тестировать через публичные методы, которые его используют. - Интеграция с CI: Test Runner может запускать тесты из командной строки, что позволяет интегрировать процесс тестирования в системы Continuous Integration (CI/CD).
Таким образом, Test Runner служит мощным и удобным центром управления тестированием, а сама практика написания юнит(unit)-тестов требует соблюдения принципов чистого кода, изоляции и четкого определения ожидаемого поведения, что в итоге значительно повышает качество и снижает риски в разработке игровых проектов на Unity.