摘要:本文从实际应用出发提出种轻量级.NET应用性能测试框架设计方案该方案是对已有结果进步扩充具有更强实用性和扩展性
1 引言
文[1]提出种.NET应用“性能测试框架”其基本思路是通过多个线程执行通过委托传递过来待测试块各线程所运行块主逻辑是相同区别是执行条件(如参数、执行次数等)这样就可以得到区别“环境”下算法执行时间进而得到整体时间消耗分布情况应该说这种思路方法思路是很清晰使用也很方便文[1]还比较详细地分析了为何采用委托而放弃“反射”、“接口”等手段主要是为了获取更为准确测试结果
但从实际应用来看这种测试还是显得不够全面它只是通过编写类似测试脚本测试来对某段核心或算法进行测试如果个应用核心算法很复杂中间步骤也很复杂则相应测试编写就变得比较烦琐比如B/S就存在大量交互过程这时如果想获取个重要业务操作执行时间上述测试框架实现起来就比较麻烦甚至有些就不能实现另外在表述上我们认为文[1]所提性能测试思路方法应当称为轻量级性能测试真正性能测试包括参考指标是很多不仅仅是执行时间
针对这些问题本文对文[1]进行了扩展给出种更为合理轻量级.NET应用性能测试框架(Light-weight Performance Testing Framework of .NET application简称LPTF)设计思路方法
2 概念和结构设计
首先我们引入“正向测试”和“反向测试”两个概念
所谓正向测试是指顺序运行应用或功能模块通过嵌入测试点最终得到各个阶段运行时间、CPU利用率、内存使用等性能指标结果反向测试则是通过编写测试对某个功能点或某段应用逻辑进行深度测试进而得出组性能指标得测试结果这里深度测试是指给定区别测试条件如执行次数、参数等
不难看出正向测试和反向测试是相互补充文[1]中测试框架即是我们这里所说反向测试
下面来看下结构设计:
er\" height=350 alt=1 src=\"/Files/BeyondPic/2007-10/20/image001.jpg\" width=483>
图2-1 整体结构图
解释:LPTF整体上包括测试逻辑、结果输出两部分测试逻辑由正向测试(StraightTest)和反向测试(ReverseTest)组成在StraightTest中我们看到有个叫作GlobalStraightTest类这是B/S在进行StraightTest时可能会有多个页面间跳转情况这时如果我们要做全局正向测试就要保存个StraightTest执行器(TestRunner)状态
测试结果输出模块(ResultOutput)会根据传递过来测试结果和指定输出模式进行结果输出它和测试逻辑是相对独立输出模式有两种DisplayOption、WebDisplayOption前者适用于C/S后者适用于B/S
er\" height=621 alt=11 src=\"/Files/BeyondPic/2007-10/20/image002.jpg\" width=544>
图2-2 正向测试结构图
解释:正向测试实现并不复杂在对B/S进行全局测试时要传入个.Web.UI.Page对象(般是当前页)用来保存TestRunner到session如果需要显示测试进度还要传入个用于反馈进度URL地址简单说就是LPTF会提供个aspx文件实际使用时可以将其放到当前项目中编译在运行时把这个文件对应URL作为TestRunner构造参数即可
StraightTest具体执行顺序大致是“生成TestRunner对象→TestRunnerRunTests思路方法启动测试→TestRunnerPhaseEnd思路方法结束个阶段测试→…→TestRunnerEnd思路方法结束测试”每次PhaseEnd和最后End思路方法都会记录当前测试结果测试结束后可GetTestResult思路方法获取全部测试结果测试结果记录每个阶段名称和相应执行时间
er\" height=796 alt=111 src=\"/Files/BeyondPic/2007-10/20/image003.jpg\" width=467>
图2-3 反向测试结构图
解释:反向测试比正向测试要复杂些主要是针对同段要准备区别执行(这里称的为测试用例TestCase般分“长时间-Max”、“中等时间-Median”、“短时间-Min” 3个测试环境)如果每个测试用例要进行些、扫尾和验证动作则还要把相应思路方法委托给PreTestCleanup、PostTestCleanup和TestValidityCheck测试执行器会根据整体测试情况计算出个般运算时间值(这里称的为规范标准值NormalisedTimeSpan)
反向测试执行过程是首先开辟个单独线程根据指定执行次数和迭代次数执行用例执行用例顺序是随机最后筛选并统计每个用例执行时间
另外反向测试中测试进度(Progress)直接写在了LPTF中这是反向测试测试都是C/S不存在URL问题可以直接写成dll
er\" height=856 alt=11111 src=\"/Files/BeyondPic/2007-10/20/image004.jpg\" width=569>
er\" height=856 alt=1111 src=\"/Files/BeyondPic/2007-10/20/image004.jpg\" width=569>
图2-4 测试结果输出引擎结构
解释: LPTF提供了丰富输出格式通过个抽象类output规范标准了统接口各种输出方式继承output并实现OutputResults思路方法output还提供了个DisplayResults思路方法动态具体输出思路方法由于正向测试和反向测试测试结果形式区别在ChartOutputForm中提供了个属性IsDisplayReverseTest用于指定是否显示反向测试结果对于WebChartOutput类会有显示图表Control控件、URL
、编译等问题最好由用户在自己应用中实现
[Page]
3 使用举例
下面是后面部分举例中会用到段
//被测试
private UInt16 _mediumFactor, _maxFactor;
public UInt16 MediumFactor
{
get { _mediumFactor;}
{_mediumFactor = value;}
}
public UInt16 MaxFactor
{
get { _maxFactor;}
{_maxFactor = value;}
}
public void FastMethod(Int32 NumberIterations)
{
j = 0;
for ( i = 0;i < NumberIterations;i)
{
j i;
}
}
public void MediumMethod(Int32 NumberIterations)
{
j = 0;
for ( i = 0;i < NumberIterations;i)
{
for ( k = 0; k < _mediumFactor; k)
j k;
}
}
public void SlowMethod(Int32 NumberIterations)
{
j = 0;
for ( i = 0;i < NumberIterations;i)
{
for ( k = 0; k < _maxFactor; k)
j k;
}
}
□ 正向测试
首先来看C/S正向测试
public DotNetPerformance.StraightTest.TestResult RunSTest
{
const numberIterations = 50000000;
DotNetPerformance.StraightTest.TestRunner tr = DotNetPerformance.StraightTest.TestRunner;
tr.RunTests;
FastMethod(numberIterations);
tr.PhaseEnd(\"Phase1\");
MediumMethod(numberIterations);
tr.PhaseEnd(\"Phase2\");
SlowMethod(numberIterations);
tr.End(\"最后个阶段\");
tr.GetTestResult;
}
private void btnST_Click(object sender, .EventArgs e)
{
DotNetPerformance.ResultOutput.Output.DisplayResults(RunSTest,
DotNetPerformance.ResultOutput.DisplayOption.Chart,null);
}
er\" height=362 alt=2 src=\"/Files/BeyondPic/2007-10/20/image006.jpg\" width=552>
图 3-1 正向测试结果-图形输出
再来看B/S单个页面里正向测试(这里用.Threading.Thread.Sleep来模拟段执行)在结果输出时要传入页面对象用于注册脚本从而显示输出测试结果
m_Tester = DotNetPerformance.StraightTest.TestRunner;
m_Tester.RunTests;
.Threading.Thread.Sleep(1000);
m_Tester.PhaseEnd(\"第阶段\");
.Threading.Thread.Sleep(100);
m_Tester.PhaseEnd(\"第 2阶段\");
.Threading.Thread.Sleep(2000);
m_Tester.PhaseEnd(\"第 3阶段\");
.Threading.Thread.Sleep(50);
m_Tester.PhaseEnd(\"第 4阶段\");
.Threading.Thread.Sleep(50);
m_Tester.End(\"第 5阶段\");
WebDisplayOption _wdo = UIHelper.ToWebDisplayOption(this.ddlOutputMode.SelectedValue);
(_wdo WebDisplayOption.WebAlert)
{
DotNetPerformance.ResultOutput.Output.DisplayResults(m_Tester.GetTestResult,_wdo, object{this.Page});
}
(_wdo WebDisplayOption.WebTable)
{
DotNetPerformance.ResultOutput.Output.DisplayResults(m_Tester.GetTestResult,_wdo, object{\"\",this.Page});
}
(_wdo WebDisplayOption.WebXml)
{
DotNetPerformance.ResultOutput.Output.DisplayResults(m_Tester.GetTestResult,_wdo, object{\"\",this.Page});
}
{
//
}
er\" height=246 alt=22 src=\"/Files/BeyondPic/2007-10/20/image008.jpg\" width=552>
图 3-2正向测试结果-Web提示输出
对于B/S多个页面间测试需要用GlobalStraightTest如果要显示测试进度还要传入个URL(前面已解释)
DotNetPerformance.StraightTest.GlobalStraightTest.WebContainerPage = this.Page;
DotNetPerformance.StraightTest.GlobalStraightTest.RunTests(\"http://localhost/LPTDemo/WaitPage.aspx\");
.Threading.Thread.Sleep(1000);
DotNetPerformance.StraightTest.GlobalStraightTest.PhaseEnd(\"第个页面阶段1\");
.Threading.Thread.Sleep(100);
DotNetPerformance.StraightTest.GlobalStraightTest.PhaseEnd(\"第个页面阶段2\");
er\" height=302 alt=222 src=\"/Files/BeyondPic/2007-10/20/image010.jpg\" width=579>
图 3-3 正向全局测试-进度条1
下面转到第 2个页面
Response.Redirect(\"MidWebForm.aspx\");
DotNetPerformance.StraightTest.GlobalStraightTest.WebContainerPage = this.Page;
.Threading.Thread.Sleep(50);
DotNetPerformance.StraightTest.GlobalStraightTest.PhaseEnd(\"第 2个页面测试结束\");
Response.Redirect(\"EndWebForm.aspx\");
er\" height=248 alt=2222 src=\"/Files/BeyondPic/2007-10/20/image012.jpg\" width=588>
图 3-4 正向全局测试-进度条2
第 3个页面
.Threading.Thread.Sleep(150);
DotNetPerformance.StraightTest.GlobalStraightTest.End(\"第 3个页面测试结束\");
WebDisplayOption _wdo = UIHelper.ToWebDisplayOption(this.ddlOutputMode.SelectedValue);
(_wdo WebDisplayOption.WebAlert)
{
DotNetPerformance.ResultOutput.Output.DisplayResults(
DotNetPerformance.StraightTest.GlobalStraightTest.GetTestResult,_wdo, object{this.Page});
}
(_wdo WebDisplayOption.WebTable)
{
???? DotNetPerformance.ResultOutput.Output.DisplayResults(
DotNetPerformance.StraightTest.GlobalStraightTest.GetTestResult,_wdo, object{\"\",this.Page});
}
(_wdo WebDisplayOption.WebXml)
{
DotNetPerformance.ResultOutput.Output.DisplayResults(
DotNetPerformance.StraightTest.GlobalStraightTest.GetTestResult,_wdo, object{\"\",this.Page});
}
{
//
}
er\" height=289 alt=22222 src=\"/Files/BeyondPic/2007-10/20/image014.jpg\" width=583>
图 3-5 正向全局测试结果-XML输出
er\" height=255 alt=33 src=\"/Files/BeyondPic/2007-10/20/image016.jpg\" width=597>
图 3-6 正向测试结果-Web表格输出
er\" height=351 alt=2222222 src=\"/Files/BeyondPic/2007-10/20/image018.jpg\" width=560>
图 3-7 正向测试结果-Web图形输出
[Page]
□ 反向测试
/// <summary>
/// 测试主调
/// </summary>
/// <s></s>
public DotNetPerformance.ReverseTest.TestResult RunTest
{
const numberIterations = 50000000;
const numberTestRuns = 5;
DotNetPerformance.ReverseTest.TestRunner tr = DotNetPerformance.ReverseTest.TestRunner(numberIterations,
numberTestRuns);
DotNetPerformance.ReverseTest.TestRunner.TestCase testCases = null;
testCases
DotNetPerformance.ReverseTest.TestRunner.TestCase(this.FastMethod);
testCases
DotNetPerformance.ReverseTest.TestRunner.TestCase(this.MediumMethod);
testCases
DotNetPerformance.ReverseTest.TestRunner.TestCase(this.SlowMethod);
tr.RunTests(testCases);
}
/// <summary>
/// 触发测试并将得到结果输出
/// </summary>
/// <param name=\"sender\"></param>
/// <param name=\"e\"></param>
private void btnTest_Click(object sender, .EventArgs e)
{
DotNetPerformance.ResultOutput.Output.DisplayResults(RunTest,
DotNetPerformance.ResultOutput.DisplayOption.Chart,null);
}
er\" height=389 alt=4 src=\"/Files/BeyondPic/2007-10/20/image020.jpg\" width=583>
图 3-8 反向测试结果-图形输出1
er\" height=329 alt=44 src=\"/Files/BeyondPic/2007-10/20/image022.jpg\" width=588>
图 3-9 反向测试结果-图形输出2
4 结论
总来说LPTF基于实际应用中测试需求提供了个比较全面轻量级性能测试框架和文[1]所给框架相比LPTF整合了更强实时进度提示、远程测试、弹性结果输出接口等
当然还是存在些不足比如反向测试脚本编写麻烦、进度条显示用到依赖于浏览器设置XMLHttpRequest技术等
最新评论