2015-09-14 37 views
1

在Visual Studio 2013 Web性能测试中,如何延迟在指定的时间段内发送“.webtest”中的第一个请求?我的网络测试是负载测试的一部分。 Web测试的第一个请求应在数据源字段指定的延迟时间之后发布。确定何时应该将请求发出很简单:如何延迟执行Web测试的第一个请求?

delayPeriod = dataSourceValue - (timeNow - loadTestStartTime) 

写这delayPeriod进入思考时间请求将导致正确的延迟。不幸的是,在收到对请求的响应后,思考时间被应用。因此,很容易将Web测试的第二个请求延迟到所需的时间。我想在之前延迟的第一次请求。

作为一种解决方法,我已将虚拟第一个请求包含到http://localhost/中,并将预期状态代码结果设置为404.所需延迟设置为此请求的思考时间。但是,这会将不需要的请求添加到localhost

背景: 我们有一个来自Web服务器的日志文件。它给出了每个请求的URL和时间。我们希望以与记录时相同的速率在该日志文件中重复请求。

回答

0

您对localhost的虚拟请求的解决方案与我所知的一样好。但是这里有一个替代方案。

两个部分:

(1)一个负载测试插件负载测试开始时间复制到Web测试上下文:

[DisplayName("Load Test Start Time")] 
[Description("Record the load test start time in the context of new web test iterations")] 
public class LoadTestStartTime : ILoadTestPlugin 
{ 
    public const string LoadTestStartTimeContextParameterName = "$LoadTestStartTime"; 

    public void Initialize(LoadTest loadTest) 
    { 
     DateTime startTime = DateTime.Now; 

     // Copy the load test start time into the context of each new test 
     loadTest.TestStarting += (sender, e) => 
     { 
      e.TestContextProperties[LoadTestStartTimeContextParameterName] = startTime; 
     }; 
    } 
} 

(2)一个网络测试插件,获取其延迟时间从中可以得到一个静态值或上下文参数,并可以HH属性:MM:SS.SSS或整数毫秒:

[DisplayName("Delay WebTest")] 
[Description("Delay the start of this WebTest by a certain amount of time.")] 
public class DelayWebTest : WebTestPlugin 
{ 
    [Description("Time to delay this WebTest, in HH:MM:SS.SSS time format or in ms (e.g. 00:01:23.456 or 83456 for 1m 23.456s delay)")] 
    public string Delay { get; set; } 

    public override void PreWebTest(object sender, PreWebTestEventArgs e) 
    { 
     DateTime start; 
     // Make sure this works when not in a load test 
     if (!e.WebTest.Context.ContainsKey("$LoadTestUserContext")) 
      start = DateTime.Now; 
     else 
      start = (DateTime)(e.WebTest.Context[LoadTestStartTime.LoadTestStartTimeContextParameterName]); 

     TimeSpan elapsed = DateTime.Now - start; 
     TimeSpan delay; 
     // Support {{context parameter}} substitutions 
     if (Delay.StartsWith("{{") && Delay.EndsWith("}}")) 
     { 
      string key = Delay.Substring(2, Delay.Length - 4); 
      object value = e.WebTest.Context[key]; 
      if (value is TimeSpan) delay = (TimeSpan)value; 
      else if (value is int) delay = new TimeSpan(0, 0, 0, 0, (int)value); 
      else if (value is string) delay = ParseDelayFromString(value as string); 
      else throw new ArgumentException("Delay value must be TimeSpan, int or string. Found: " + value.GetType()); 
     } 
     else delay = ParseDelayFromString(Delay); 

     TimeSpan sleep = delay - elapsed; 
     if (sleep > new TimeSpan(0)) 
     { 
      e.WebTest.AddCommentToResult("Current time: " + DateTime.Now); 
      e.WebTest.AddCommentToResult("About to sleep for " + sleep); 
      System.Threading.Thread.Sleep(sleep); 
      e.WebTest.AddCommentToResult("Current time: " + DateTime.Now); 
     } 
    } 

    public static TimeSpan ParseDelayFromString(string s) 
    { 
     TimeSpan ts; 
     if (TimeSpan.TryParse(s, out ts)) return ts; 
     int i; 
     if (int.TryParse(s, out i)) return new TimeSpan(0, 0, 0, 0, (int)i); 
     throw new FormatException("Could not parse value as TimeSpan or int: " + s); 
    } 
} 

这似乎为我工作。

但是它使用Thread.Sleep,“...不推荐用于 Web测试是因为它是一个阻塞API,并且多个Web测试可以共享一个线程,因此它可能会对多个vuser产生不利影响。 “ (See Visual Studio Performance Testing Quick Reference Guide)第187页。

因此,对于单用户负载测试以及对于虚拟用户数量不超过线程的小负载,这肯定是可以的,但很可能会导致更大负载的结果。

(*我并不知道线程模型的工作原理不过)

+0

这个答案的主要部分是'了Thread.Sleep(...)'调用,它曾是我的第一件事情。正如你在答案中所说的那样,它阻止了整个线程,因此只能为极少数的虚拟用户工作。请在VSPTQRG中提供页码。 – AdrianHHH

1

OK,再出手吧。光秃秃的骨头,但没有错误检查。

LoadTestStartTime负载测试插件将对负载测试本身和负载测试开始时间的引用放入Web测试上下文中。

public class LoadTestStartTime : ILoadTestPlugin 
{ 
    public const string LoadTestContextParameterName = "$LoadTest"; 
    public const string LoadTestStartTimeContextParameterName = "$LoadTestStartTime"; 

    public void Initialize(LoadTest loadTest) 
    { 
     DateTime startTime = default(DateTime); 

     loadTest.LoadTestStarting += (sender, e) => { startTime = DateTime.Now; }; 

     loadTest.TestStarting += (sender,e) => { 
      e.TestContextProperties[LoadTestContextParameterName] = loadTest; 
      e.TestContextProperties[LoadTestStartTimeContextParameterName] = startTime; 
     }; 
    } 
} 

DelayWebTest Web测试插件必须附加到包含一个虚拟请求的新Web测试(虚拟请求将不会执行)。这个新的Web测试必须作为“初始化测试”添加到负载测试场景测试组合中。

Initialize Test Initialize Test

插件读取上下文参数的延迟时间,然后设置方案的电流负载为0。然后,它设置了一个定时器,在正确计算的延迟之后调用的事件处理程序,其恢复负载配置文件允许进行测试。它使用锁定,以便只有第一个虚拟用户将在其他人等待时执行负载配置文件逻辑。

public class DelayWebTest : WebTestPlugin 
{ 
    public string ContextParameterName { get; set; } 

    private bool completed = false; 
    private object _lock = new object(); 

    public override void PreRequest(object sender, PreRequestEventArgs e) 
    { 
     e.Instruction = WebTestExecutionInstruction.Skip; 
     if (!completed) 
     { 
      lock (_lock) 
      { 
       if (!completed) 
       { 
        if (e.WebTest.Context.WebTestUserId > 0) return; 
        LoadTest loadTest = (LoadTest)e.WebTest.Context[LoadTestStartTime.LoadTestContextParameterName]; 
        DateTime startTime = (DateTime)e.WebTest.Context[LoadTestStartTime.LoadTestStartTimeContextParameterName]; 
        TimeSpan delay = TimeSpan.Parse(e.WebTest.Context[ContextParameterName].ToString()); 
        TimeSpan timer = delay - (DateTime.Now - startTime); 
        if (timer > default(TimeSpan)) 
        { 
         var loadProfile = loadTest.Scenarios[0].LoadProfile.Copy(); 
         loadTest.Scenarios[0].CurrentLoad = 0; 
         Timer t = new Timer() { AutoReset = false, Enabled = true, Interval = timer.TotalMilliseconds }; 
         t.Elapsed += (_sender, _e) => 
         { 
          loadTest.Scenarios[0].LoadProfile = loadProfile; 
          t.Stop(); 
         }; 
         t.Start(); 
        } 
        completed = true; 
       } 
      } 
     } 
    } 
} 

似乎工作。 50个用户提供30秒延迟:

50 users with 30 second delay

+0

问题中的解决方法允许我执行所需的测试,因此我不再需要花时间讨论此主题,而是感谢您的想法。问题在于延迟个人网络测试,而不是延迟情况。 – AdrianHHH

+0

感谢'e.Instruction = WebTestExecutionInstruction.Skip;' – AdrianHHH