如何在Teamcity上使用ApprovalTests?

时间:2022-05-05 15:06:04

I am using Approval Tests. On my dev machine I am happy with DiffReporter that starts TortoiseDiff when my test results differ from approved:

我正在使用审批测试。在我的开发机器上,我很满意DiffReporter在我的测试结果与批准的不同时启动TortoiseDiff:

    [UseReporter(typeof (DiffReporter))]
    public class MyApprovalTests
    { ... }

However when the same tests are running on Teamcity and results are different tests fail with the following error:

但是,当在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

Obviously it cannot find tortoisemerge.exe and that is fine because it is not installed on build agent. But what if it gets installed? Then for each fail another instance of tortoisemerge.exe will start and nobody will close it. Eventually tons of tortoisemerge.exe instances will kill our servers :)

显然它找不到tortoisemerge.exe,这很好,因为它没有安装在构建代理上。但是如果它被安装怎么办?然后对于每个失败,另一个tortoisemerge.exe实例将启动,没有人会关闭它。最终吨的tortoisemerge.exe实例将杀死我们的服务器:)

So the question is -- how tests should be decorated to run Tortoise Diff on local machine and just report errors on build server? I am aware of #IF DEBUG [UseReporter(typeof (DiffReporter))] but would prefer another solution if possible.

所以问题是 - 如何修改测试以在本地计算机上运行Tortoise Diff并仅在构建服务器上报告错误?我知道#IF DEBUG [UseReporter(typeof(DiffReporter))]但是如果可能的话会更喜欢另一种解决方案。

4 个解决方案

#1


9  

There are a couple of solutions to the question of Reporters and CI. I will list them all, then point to a better solution, which is not quite enabled yet.

记者和CI的问题有几个解决方案。我将列出所有这些,然后指向一个更好的解决方案,这还没有完全启用。

  1. Use the AppConfigReporter. This allows you to set the reporter in your AppConfig, and you can use the QuietReporter for CI. There is a video here, along with many other reporters. The AppConfigReporter appears at 6:00. This has the advantage of separate configs, and you can decorate at the assembly level, but has the disadvantage of if you override at the class/method level, you still have the issue.

    使用AppConfigReporter。这允许您在AppConfig中设置报告者,并且可以使用QuietReporter for CI。这里有一个视频,还有很多其他的记者。 AppConfigReporter出现在6:00。这具有单独配置的优点,并且您可以在程序集级别进行装饰,但是缺点是如果在类/方法级别覆盖,则仍然存在问题。

  2. Create your own (2) reporters. It is worth noting that if you use a reporter, it will get called, regardless as to if it is working in the environment. IEnvironmentAwareReporter allows for composite reporters, but will not prevent a direct call to the reporter. Most likely you will need 2 reporters, one which does nothing (like a quiet reporter) but only works on your CI server, or when called by TeamCity. Will call it the TeamCity Reporter. And One, which is a multiReporter which Calls teamCity if it is working, otherwise defers to .

    创建自己的(2)记者。值得注意的是,如果您使用记者,它将被调用,无论它是否在环境中工作。 IEnvironmentAwareReporter允许复合记者,但不会阻止直接调用记者。很可能你需要2个记者,一个什么都不做(比如一个安静的记者)但只能在你的CI服务器上工作,或者在TeamCity调用时。将其称为TeamCity Reporter。和One,这是一个multiReporter,如果它正在工作,它会调用teamCity,否则就会推迟。

  3. Use a FrontLoadedReporter (not quite ready). This is how ApprovalTests currently uses NCrunch. It does the above method in front of whatever is loaded in your UseReporter attribute. I have been meaning to add an assembly level attribute for configuring this, but haven't yet (sorry) I will try to add this very soon.

    使用FrontLoadedReporter(还没准备好)。这就是ApprovalTests目前使用NCrunch的方式。它在UseReporter属性中加载的任何内容之前执行上述方法。我一直想添加一个程序集级属性来配置它,但还没有(抱歉)我会尽快添加它。

Hope this helps. Llewellyn

希望这可以帮助。卢埃林

#2


4  

I recently came into this problem myself.

我最近自己遇到了这个问题。

Borrowing from xunit and how they deal with TeamCity logging I came up with a TeamCity Reporter based on the NCrunch Reporter.

借用xunit以及他们如何处理TeamCity日志,我想出了一个基于NCrunch Reporter的TeamCity Reporter。

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;
    }
}

And so I could combine it with the NCrunch reporter:

所以我可以将它与NCrunch记者结合起来:

public class TeamCityOrNCrunchReporter : FirstWorkingReporter
{
    public static readonly TeamCityOrNCrunchReporter INSTANCE = 
        new TeamCityOrNCrunchReporter();

    public TeamCityOrNCrunchReporter()
        : base(NCrunchReporter.INSTANCE,
        TeamCityReporter.INSTANCE) { }
}

[assembly: FrontLoadedReporter(typeof(TeamCityOrNCrunchReporter))]

#3


2  

I just came up with one small idea.

我想出了一个小小的想法。

You can implement your own reporter, let's call it DebugReporter

您可以实现自己的记者,让我们称之为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
    }
}

Example of usage,

使用示例,

[UseReporter(typeof(DebugReporter<FileLauncherReporter>))]
public class SomeTests
{
    [Test]
    public void test()
    {
        Approvals.Verify("Hello");
    }
}

If test is faling, it still would be red - but reporter would not came up.

如果测试是faling,它仍然会是红色 - 但记者不会出现。

The IEnvironmentAwareReporter is specially defined for that, but unfortunatelly whatever I return there, it still calls Report() method. So, I put the IsWorkingInThisEnvironment() call inside, which is a little hackish, but works :)

IEnvironmentAwareReporter是专门为此定义的,但不幸的是,无论我在那里返回什么,它仍然调用Report()方法。所以,我把IsWorkingInThisEnvironment()调用放在里面,这有点hackish,但工作:)

Hope that Llywelyn can explain why it acts like that. (bug?)

希望Llywelyn可以解释为什么它会像那样。 (错误?)

#4


1  

I'm using CC.NET and I do have TortoiseSVN installed on the server.

我正在使用CC.NET,我在服务器上安装了TortoiseSVN。

I reconfigured my build server to allow the CC.NET service to interact with the desktop. When I did that, TortiseMerge launched. So I think what's happening is that Approvals tries to launch the tool, but it cant because CC.NET is running as a service and the operating system prevents that behavior by default. If TeamCity runs as a service, you should be fine, but you might want to test.

我重新配置了构建服务器以允许CC.NET服务与桌面交互。当我这样做时,TortiseMerge推出。所以我认为正在发生的事情是Approvals尝试启动该工具,但它不能因为CC.NET作为服务运行而且操作系统默认会阻止该行为。如果TeamCity作为服务运行,您应该没问题,但您可能想要测试。

#1


9  

There are a couple of solutions to the question of Reporters and CI. I will list them all, then point to a better solution, which is not quite enabled yet.

记者和CI的问题有几个解决方案。我将列出所有这些,然后指向一个更好的解决方案,这还没有完全启用。

  1. Use the AppConfigReporter. This allows you to set the reporter in your AppConfig, and you can use the QuietReporter for CI. There is a video here, along with many other reporters. The AppConfigReporter appears at 6:00. This has the advantage of separate configs, and you can decorate at the assembly level, but has the disadvantage of if you override at the class/method level, you still have the issue.

    使用AppConfigReporter。这允许您在AppConfig中设置报告者,并且可以使用QuietReporter for CI。这里有一个视频,还有很多其他的记者。 AppConfigReporter出现在6:00。这具有单独配置的优点,并且您可以在程序集级别进行装饰,但是缺点是如果在类/方法级别覆盖,则仍然存在问题。

  2. Create your own (2) reporters. It is worth noting that if you use a reporter, it will get called, regardless as to if it is working in the environment. IEnvironmentAwareReporter allows for composite reporters, but will not prevent a direct call to the reporter. Most likely you will need 2 reporters, one which does nothing (like a quiet reporter) but only works on your CI server, or when called by TeamCity. Will call it the TeamCity Reporter. And One, which is a multiReporter which Calls teamCity if it is working, otherwise defers to .

    创建自己的(2)记者。值得注意的是,如果您使用记者,它将被调用,无论它是否在环境中工作。 IEnvironmentAwareReporter允许复合记者,但不会阻止直接调用记者。很可能你需要2个记者,一个什么都不做(比如一个安静的记者)但只能在你的CI服务器上工作,或者在TeamCity调用时。将其称为TeamCity Reporter。和One,这是一个multiReporter,如果它正在工作,它会调用teamCity,否则就会推迟。

  3. Use a FrontLoadedReporter (not quite ready). This is how ApprovalTests currently uses NCrunch. It does the above method in front of whatever is loaded in your UseReporter attribute. I have been meaning to add an assembly level attribute for configuring this, but haven't yet (sorry) I will try to add this very soon.

    使用FrontLoadedReporter(还没准备好)。这就是ApprovalTests目前使用NCrunch的方式。它在UseReporter属性中加载的任何内容之前执行上述方法。我一直想添加一个程序集级属性来配置它,但还没有(抱歉)我会尽快添加它。

Hope this helps. Llewellyn

希望这可以帮助。卢埃林

#2


4  

I recently came into this problem myself.

我最近自己遇到了这个问题。

Borrowing from xunit and how they deal with TeamCity logging I came up with a TeamCity Reporter based on the NCrunch Reporter.

借用xunit以及他们如何处理TeamCity日志,我想出了一个基于NCrunch Reporter的TeamCity Reporter。

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;
    }
}

And so I could combine it with the NCrunch reporter:

所以我可以将它与NCrunch记者结合起来:

public class TeamCityOrNCrunchReporter : FirstWorkingReporter
{
    public static readonly TeamCityOrNCrunchReporter INSTANCE = 
        new TeamCityOrNCrunchReporter();

    public TeamCityOrNCrunchReporter()
        : base(NCrunchReporter.INSTANCE,
        TeamCityReporter.INSTANCE) { }
}

[assembly: FrontLoadedReporter(typeof(TeamCityOrNCrunchReporter))]

#3


2  

I just came up with one small idea.

我想出了一个小小的想法。

You can implement your own reporter, let's call it DebugReporter

您可以实现自己的记者,让我们称之为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
    }
}

Example of usage,

使用示例,

[UseReporter(typeof(DebugReporter<FileLauncherReporter>))]
public class SomeTests
{
    [Test]
    public void test()
    {
        Approvals.Verify("Hello");
    }
}

If test is faling, it still would be red - but reporter would not came up.

如果测试是faling,它仍然会是红色 - 但记者不会出现。

The IEnvironmentAwareReporter is specially defined for that, but unfortunatelly whatever I return there, it still calls Report() method. So, I put the IsWorkingInThisEnvironment() call inside, which is a little hackish, but works :)

IEnvironmentAwareReporter是专门为此定义的,但不幸的是,无论我在那里返回什么,它仍然调用Report()方法。所以,我把IsWorkingInThisEnvironment()调用放在里面,这有点hackish,但工作:)

Hope that Llywelyn can explain why it acts like that. (bug?)

希望Llywelyn可以解释为什么它会像那样。 (错误?)

#4


1  

I'm using CC.NET and I do have TortoiseSVN installed on the server.

我正在使用CC.NET,我在服务器上安装了TortoiseSVN。

I reconfigured my build server to allow the CC.NET service to interact with the desktop. When I did that, TortiseMerge launched. So I think what's happening is that Approvals tries to launch the tool, but it cant because CC.NET is running as a service and the operating system prevents that behavior by default. If TeamCity runs as a service, you should be fine, but you might want to test.

我重新配置了构建服务器以允许CC.NET服务与桌面交互。当我这样做时,TortiseMerge推出。所以我认为正在发生的事情是Approvals尝试启动该工具,但它不能因为CC.NET作为服务运行而且操作系统默认会阻止该行为。如果TeamCity作为服务运行,您应该没问题,但您可能想要测试。