2015-09-14 45 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