Введение в Unit-тестирование с использованием Revit
Здравствуйте, уважаемые коллеги. Сегодня рассмотрим интересную и новую для меня тему: автоматическое тестирование с использованием Revit. Сильно усложнять не буду, просто покажу, как писать тесты и запускать их, а дальше, как и обычно, простор для вашей фантазии безграничен. Вдохновляйтесь и запускайте их как вашей душе (и бизнес-процессам вашей организации) угодно.
1. Введение
В этой статье я не буду изобретать велосипед, а просто расскажу, как подключить готовый фреймворк для тестирования внутри Revit от Романа Карповича Nice3Point.RevitUnit. Для локального старта вам понадобится установленный на компьютере лицензионный Revit, а также самая новая версия шаблонов от Романа
2. Развёртывание проекта
Создадим новое решение с шаблоном Revit Addin Solution:
Создание решения
Внутри решения создадим 2 проекта: один с шаблоном Revit Addin Module, а второй — Revit Test (TUnit)
Создание проекта для тестов
В проекте для тестов мы будем непосредственно писать тесты, а в Addin Module напишем некоторый код, который будет использоваться как реальным плагином (у меня его нет, у вас будет), так и проектом с тестами. Давайте рассмотрим файл с ревит-тестами:
public sealed class RevitTests : RevitApiTest
{
private Document _document = null!;
[Before(Test)]
[HookExecutor<RevitThreadExecutor>]
public void SeedModel()
{
_document = Application.NewProjectDocument(UnitSystem.Metric);
using var transaction = new Transaction(_document, "Seed model");
transaction.Start();
transaction.Commit();
}
[After(Test)]
[HookExecutor<RevitThreadExecutor>]
public void CloseModel()
{
_document.Close(false);
}
[Test]
public async Task RevitTest()
{
// Arrange
// Act
// Assert
// await Assert.That();
}
}
Тут структура такая:
- атрибутом [Before(Test)] мы помечаем метод, который будет выполнен перед началом тестирования. Там мы открываем или создаём документ и сохраняем его в поле класса
- атрибутом [After(Test)] мы помечаем метод, который будет выполняться после тестирования. В данном случае мы закрываем документ. Но в целом, никто не запрещает нам сохранить его, или вообще сделать всё что угодно.
- атрибутом [Test] помечаются тесты, которые будут выполняться при запуске тестирования. Тут обычная структура Arrange-Act-Assert — подготовка-действие-проверка
Напишем сервис, который мы будем тестировать. Он будет генерировать заданное количество стен, а проверить мы будем, сколько стен он создал:
public class ElementPlacementService
{
public void PlaceWalls(Document document, int count)
{
var level = document
.CollectElements()
.Instances()
.OfType<Level>()
.First();
for (var i = 0; i < count; i++)
{
var start = new XYZ(i, 0, 0);
var end = new XYZ(i, 10, 0);
var line = Line.CreateBound(start, end);
Wall.Create(document, line, level.Id, false);
}
}
}
Теперь давайте напишем тест для этого кода:
[Test]
public async Task WallPlacementTest()
{
// Arrange
var service = new ElementPlacementService();
var wallsNumber = Random.Shared.Next(1, 10);
// Act
using var transaction = new Transaction(_document, "Seed model");
transaction.Start();
service.PlaceWalls(_document, wallsNumber);
transaction.Commit();
// Assert
var count = _document
.CollectElements()
.Instances()
.OfCategory(BuiltInCategory.OST_Walls)
.Count();
await Assert.That(count).IsEqualTo(wallsNumber);
}
Всё, первый тест написан. Запускаем:
- открываем терминал в Rider:
Терминал
Обратите внимание на путь, который я обвёл красным. Это должен быть путь к нашему проекту с тестами. Если путь другой, проект не запустится. Поэтому я вызываю команду ‘cd’ чтобы перейти в нужную директорию:
cd .\tests\RevitUnitTests\
У вас могут быть другие папки
- запускаем команду:
dotnet run -c "Release.R25"
Указав вместо R25 вашу версию Revit. Вот что мы видим в терминале по завершению (Revit открылся фоново, как юзеры мы это не заметили):
Результат выполнения
Я добавил код, чтобы сохранить тестовый файл на диск после окончания тестов, только чтобы убедиться, что какие-то действия действительно происходят:
[After(Test)]
[HookExecutor<RevitThreadExecutor>]
public void CloseModel()
{
_document.SaveAs(@"C:\Users\Sergei Nefyodov\Downloads\test.rvt", new SaveAsOptions
{
MaximumBackups = 1,
OverwriteExistingFile = true
});
_document.Close(false);
}
И действительно, там хранится случайное число стен от 1 до 10, длиной 10 футов, как и было написано в коде
Тестовый файл со стенами в 10 футов длиной
Заключение
Сегодня мы узнали, как создавать и запускать Unit-тесты, использующие Revit под капотом. Это действительно крутая штука, которая позволяет автоматизировать тестирование и быстро проверять, что новый код не сломал ничего существующего, и повышать качество кода. Огромное спасибо Роману Карповичу от лица всех моих читателей за упрощение жизни и развитие Revit API-коммьюнити с помощью своих классных шаблонов и инструментов
Код из статьи можно посмотреть здесь.
Спасибо за внимание и до новых встреч! Подписывайтесь на мой телеграм-канал!