据我所知,您对 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) 一个 web 测试插件,它从一个可以是静态值或上下文参数的属性中获取延迟时间,可以是 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 页。
所以这对于单用户负载测试当然是可以的,也许对于虚拟用户数量不超过线程数的小负载*,但它可能会在更大负载时搞砸结果。
(* 我不声称知道线程模型是如何工作的)