← Назад к вопросам

Как писать Unit-тесты в Unity? Что такое Test Runner?

2.3 Middle🔥 182 комментариев
#Unity Core

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как писать 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.