我可以在Visual Studio中为UnitTest/LoadTest创建自定义TestContext计时器吗?

esa*_*sac 10 c# unit-testing load-testing visual-studio test-framework

我的一些UnitTests有一个在循环中定义的Sleep.我想不仅要描述测试的每次迭代,而且要描述所有迭代的总时间,以便显示任何非线性缩放.例如,如果我描述"整体",它包括睡眠时间.我可以使用StopwatchStart/Stop以便它只包含doAction().但是,我无法将Stopwatch结果写入TestContext结果.

[TestMethod]
    public void TestMethod1()
    {
        TestContext.BeginTimer("Overall");
        for (int i = 0; i < 5; i++)
        {
            TestContext.BeginTimer("Per");
            doAction();
            TestContext.EndTimer("Per");
            Sleep(1000);
        }
        TestContext.EndTimer("Overall");
    }
Run Code Online (Sandbox Code Playgroud)

看起来TestContext可以继承并重新定义.但是,我没有看到任何关于如何将其写回事务存储的示例.

是否有我可以参考的实现,或其他想法.我希望在Visual Studio为LoadTest提供的报告中看到它.否则我必须写自己的报告.

此外,我试图嗅探将这些写入LoadTest数据库的SQL,但是没有成功地弄清楚如何.应该有一个SPROC来调用,但我认为它是测试结束时的所有数据.

cha*_*sos 9

好吧,我遇到了类似的问题.我想在最终测试结果中报告我的测试中的一些额外数据/报告/计数器,就像Visual Studio一样,我找到了一个解决方案.

首先,这不能用你尝试的方式来完成.Load Test和Test Test存在的单元测试之间没有直接的联系.

其次,您必须了解visual studio如何创建报告.它从OS 的性能计数器收集数据.您可以编辑这些计数器,删除不需要的计数器并添加其他所需的计数器.

如何编辑计数器

负载测试配置有两个关于计数器的基本部分.这些是:

  • Counter Sets.这些是计数器集,例如agent默认情况下添加的计数器集.如果打开此计数器集,您将看到它收集内存,处理器,物理磁盘等计数器.因此,在测试结束时,您可以看到所有代理的所有这些数据.如果要在此计数器集中添加更多计数器,可以双击它(从负载测试编辑器,见下图)并选择Add Counters.这将打开一个包含系统所有计数器的窗口,并选择您想要的那些.

  • Counter Set Mappings.在这里,您可以将计数器组与您的机器相关联 默认情况下,[CONTROLLER MACHINE][AGENT MACHINES]添加了一些默认计数器集.这意味着计数器集中包含的所有计数器都[CONTROLLER MACHINE]将从控制器计算机中收集.这同样适用于所有代理商.

在此输入图像描述

您可以添加更多计数器集和更多计算机.通过右键单击Counter Set Mappings- >,Manage Counter Sets...将打开一个新窗口,如下所示:

在此输入图像描述

如您所见,我添加了一个额外的机器名称db_1.这是计算机的计算机名称,它必须与控制器位于同一个域中才能访问它并收集计数器.我还将其标记为database server并选择了sql计数器集(默认为sql计数器,但您可以编辑它并添加您想要的任何计数器).现在,每次执行此负载测试时,控制器将转到计算机名为db_1的计算机,并收集将在最终测试结果中报告的数据.


现在是编码部分

好的,在这个(大)介绍之后,是时候看看如何将你的数据添加到最终的测试结果中了.为此,您必须创建自己的自定义性能计数器.这意味着必须在收集这些数据所需的计算机中创建新的性能计数器类别.在您的情况下,在所有代理中,因为这是UnitTests的执行位置.

在代理中创建计数器后,您可以编辑Agents计数器集,如上所示,并选择额外的自定义计数器.

以下是有关如何执行此操作的示例代码.

首先为所有代理创建性能计数器.在每个代理计算机上只运行一次此代码(或者您可以将其添加到负载测试插件中):

void CreateCounter() 
{
    if (PerformanceCounterCategory.Exists("MyCounters"))
    {
        PerformanceCounterCategory.Delete("MyCounters");
    }

    //Create the Counters collection and add your custom counters 
    CounterCreationDataCollection counters = new CounterCreationDataCollection();
    // The name of the counter is Delay
    counters.Add(new CounterCreationData("Delay", "Keeps the actual delay", PerformanceCounterType.AverageCount64));
    // .... Add the rest counters

    // Create the custom counter category
    PerformanceCounterCategory.Create("MyCounters", "Custom Performance Counters", PerformanceCounterCategoryType.MultiInstance, counters);
}
Run Code Online (Sandbox Code Playgroud)

在这里你的测试代码:

[TestClass]
public class UnitTest1
{
    PerformanceCounter OverallDelay;
    PerformanceCounter PerDelay;

    [ClassInitialize]
    public static void ClassInitialize(TestContext TestContext)
    {
        // Create the instances of the counters for the current test
        // Initialize it here so it will created only once for this test class
        OverallDelay= new PerformanceCounter("MyCounters", "Delay", "Overall", false));
        PerDelay= new PerformanceCounter("MyCounters", "Delay", "Per", false));
        // .... Add the rest counters instances
    }

    [ClassCleanup]
    public void CleanUp()
    {
        // Reset the counters and remove the counter instances
        OverallDelay.RawValue = 0;
        OverallDelay.EndInit();
        OverallDelay.RemoveInstance();
        OverallDelay.Dispose();
        PerDelay.RawValue = 0;
        PerDelay.EndInit();
        PerDelay.RemoveInstance();
        PerDelay.Dispose();
    }

    [TestMethod]
    public void TestMethod1()
    {
         // Use stopwatch to keep track of the the delay
         Stopwatch overall = new Stopwatch();
         Stopwatch per = new Stopwatch();

         overall.Start();

         for (int i = 0; i < 5; i++)
         {
             per.Start();
             doAction();
             per.Stop();

             // Update the "Per" instance of the "Delay" counter for each doAction on every test
             PerDelay.Incerement(per.ElapsedMilliseconds);
             Sleep(1000);

             per.Reset();
         }

         overall.Stop();

         // Update the "Overall" instance of the "Delay" counter on every test
         OverallDelay.Incerement(overall.ElapsedMilliseconds);
     }
}
Run Code Online (Sandbox Code Playgroud)

现在,当您的测试执行时,他们会向计数器报告他们的数据.在负载测试结束时,您将能够在每个代理计算机中查看计数器并将其添加到图表中.它将以MIN,MAX和AVG值报告.

结论

  1. 我认为(经过数月的研究),这是将测试中的自定义数据添加到最终负载测试报告的唯一方法.
  2. 这样做似乎太难了.好吧,如果您理解这一点,那么优化它并不困难.我已将此功能包装在一个类中,以便更容易初始化,更新并最终管理计数器.
  3. 这非常有用.我现在可以从我的测试中看到使用默认计数器无法实现的统计数据.这样我们,当Web服务的Web请求失败时,我可以捕获错误并更新相应的计数器(例如Timeout,ServiceUnavailable,RequestRejected ...).

我希望我帮忙.:)