Как использовать тесты одобрения Teamcity?
Я использую Тесты одобрения. На моей машине dev я доволен тем, что DiffReporter
запускает TortoiseDiff, когда мои результаты теста отличаются от утвержденных:
[UseReporter(typeof (DiffReporter))]
public class MyApprovalTests
{ ... }
Однако, когда те же тесты выполняются на Teamcity, а результаты разные тесты терпят неудачу со следующей ошибкой:
System.Exception : Unable to launch: tortoisemerge.exe with arguments ...
Error Message: The system cannot find the file specified
---- System.ComponentModel.Win32Exception : The system cannot find the file
specified
Очевидно, он не может найти tortoisemerge.exe, и это нормально, потому что он не установлен на агенте сборки. Но что, если он будет установлен? Затем для каждого отказа запускается другой экземпляр tortoisemerge.exe, и никто его не закрывает. В конце концов, количество экземпляров tortoisemerge.exe убьет наши серверы:)
Итак, вопрос в том, как должны быть оформлены тесты для запуска Tortoise Diff на локальной машине
и просто сообщать об ошибках на сервере сборки? Я знаю #IF DEBUG [UseReporter(typeof (DiffReporter))]
, но предпочитаю другое решение, если это возможно.
Ответы
Ответ 1
Есть несколько вариантов решения проблемы Репортеров и CI. Я перечислил их все, а затем укажу на лучшее решение, которое пока еще не реализовано.
-
Используйте AppConfigReporter. Это позволяет вам установить репортер в AppConfig, и вы можете использовать QuietReporter для CI.
Здесь есть видео, а также многие другие репортеры. AppConfigReporter появляется в 6:00.
Это имеет преимущество отдельных конфигураций, и вы можете украшать на уровне сборки, но имеет недостаток, если вы переопределяете уровень класса/метода, у вас все еще есть проблема.
-
Создайте собственных (2) репортеров. Стоит отметить, что если вы используете репортера, он будет вызван, независимо от того, работает ли он в среде. IEnvironmentAwareReporter позволяет создавать составные репортеры, но не препятствует прямому обращению к репортеру.
Скорее всего, вам понадобятся 2 репортера, которые ничего не делают (например, довольно репортер), но работают только на вашем сервере CI или при вызове TeamCity. Назовут его репортером TeamCity. И один, который является мультирепортером, который вызывает команду teamCity, если он работает, в противном случае откладывает.
-
Используйте FrontLoadedReporter (не совсем готов). Это то, как ApprovedTests в настоящее время использует NCrunch. Он выполняет вышеуказанный метод перед тем, что загружается в ваш атрибут UseReporter. Я хотел бы добавить атрибут уровня сборки для его настройки, но еще нет (извините), я постараюсь добавить это очень скоро.
Надеюсь, это поможет.
Llewellyn
Ответ 2
Недавно я сам вошел в эту проблему.
Заимствование из xunit и то, как они работают с протоколированием TeamCity, я придумал TeamCity Reporter на основе репортера NCrunch.
public class TeamCityReporter : IEnvironmentAwareReporter, IApprovalFailureReporter
{
public static readonly TeamCityReporter INSTANCE = new TeamCityReporter();
public void Report(string approved, string received) { }
public bool IsWorkingInThisEnvironment(string forFile)
{
return Environment.GetEnvironmentVariable("TEAMCITY_PROJECT_NAME") != null;
}
}
И поэтому я мог бы объединить его с репортером NCrunch:
public class TeamCityOrNCrunchReporter : FirstWorkingReporter
{
public static readonly TeamCityOrNCrunchReporter INSTANCE =
new TeamCityOrNCrunchReporter();
public TeamCityOrNCrunchReporter()
: base(NCrunchReporter.INSTANCE,
TeamCityReporter.INSTANCE) { }
}
[assembly: FrontLoadedReporter(typeof(TeamCityOrNCrunchReporter))]
Ответ 3
Я только придумал одну маленькую идею.
Вы можете реализовать своего собственного репортера, позвоните ему DebugReporter
public class DebugReporter<T> : IEnvironmentAwareReporter where T : IApprovalFailureReporter, new()
{
private readonly T _reporter;
public static readonly DebugReporter<T> INSTANCE = new DebugReporter<T>();
public DebugReporter()
{
_reporter = new T();
}
public void Report(string approved, string received)
{
if (IsWorkingInThisEnvironment())
{
_reporter.Report(approved, received);
}
}
public bool IsWorkingInThisEnvironment()
{
#if DEBUG
return true;
#else
return false;
#endif
}
}
Пример использования,
[UseReporter(typeof(DebugReporter<FileLauncherReporter>))]
public class SomeTests
{
[Test]
public void test()
{
Approvals.Verify("Hello");
}
}
Если тест фальсифицирован, он все равно будет красным - но репортер не подошел бы.
IEnvironmentAwareReporter
специально определен для этого, но, к сожалению, все, что я туда вернусь, все равно вызывает метод Report(). Итак, я помещаю вызов IsWorkingInThisEnvironment() внутри, что немного хакерское, но работает:)
Надеюсь, что Llywelyn может объяснить, почему он действует так. (Ошибка?)
Ответ 4
Я использую CC.NET, и у меня есть TortoiseSVN, установленный на сервере.
Я переконфигурировал свой сервер сборки, чтобы позволить службе CC.NET взаимодействовать с рабочим столом. Когда я это сделал, TortiseMerge запущен. Поэтому я думаю, что происходит то, что Approvals пытается запустить этот инструмент, но это не так, потому что CC.NET работает как служба, а операционная система предотвращает это поведение по умолчанию. Если TeamCity работает как служба, вы должны быть в порядке, но вы можете протестировать.