分享
 
 
 

一种改进的轻量级.NET应用程序性能测试框架

王朝c#·作者佚名  2006-01-31
窄屏简体版  字體: |||超大  

摘要:本文从实际应用出发,提出一种轻量级.NET应用程序性能测试框架设计方案。该方案是对已有结果的进一步扩充,具有更强的实用性和扩展性。

1 引言

文[1]提出一种.NET应用程序“性能测试框架”,其基本思路是通过多个线程执行通过委托传递过来的待测试的程序块,各线程所运行的程序块的主逻辑是相同的,不同的是执行条件(如初始参数、执行次数等)。这样就可以得到不同“环境”下算法的执行时间,进而得到整体的时间消耗分布情况。应该说,这种方法的思路是很清晰的,使用也很方便。文[1]还比较详细地分析了为何采用委托而放弃“反射”、“接口”等手段,主要是为了获取更为准确的测试结果。

但从实际应用来看这种测试还是显得不够全面,它只是通过编写类似测试脚本的测试程序来对某段核心程序或算法进行测试。如果一个应用程序的核心算法很复杂,中间步骤也很复杂,则相应的测试程序编写就变得比较烦琐。比如B/S程序就存在大量的交互过程,这时如果想获取一个重要业务操作的执行时间,上述测试框架实现起来就比较麻烦,甚至有些就不能实现。另外,在表述上我们认为文[1]所提性能测试方法应当称为轻量级性能测试,因为真正的性能测试包括的参考指标是很多的,不仅仅是执行时间。

针对这些问题,本文对文[1]进行了扩展,给出一种更为合理的轻量级.NET应用程序性能测试框架(Light-weight Performance Testing Framework of .NET application,简称LPTF)设计方法。

2 概念与结构设计

首先,我们引入“正向测试”和“反向测试”两个概念。

所谓正向测试是指顺序运行应用程序或功能模块,通过嵌入测试点,最终得到各个阶段的运行时间、CPU利用率、内存使用等性能指标的结果。反向测试则是通过编写测试程序对某个功能点或某段应用逻辑进行深度测试,进而得出一组性能指标得测试结果。这里的深度测试是指给定不同的测试条件,如执行次数、初始参数等。

不难看出,正向测试和反向测试是相互补充的,文[1]中的测试框架即是我们这里所说的反向测试。

下面来看一下结构设计:

图2-1 整体结构图

解释:LPTF整体上包括测试逻辑、结果输出两部分。测试逻辑由正向测试(StraightTest)和反向测试(ReverseTest)组成。在StraightTest中我们看到有一个叫作GlobalStraightTest的类,这是因为B/S程序在进行StraightTest时可能会有多个页面间跳转的情况,这时如果我们要做全局的正向测试就要保存一个StraightTest的执行器(TestRunner)的状态。

测试结果输出模块(ResultOutput)会根据传递过来的测试结果和指定的输出模式进行结果输出,它和测试逻辑是相对独立的。输出模式有两种DisplayOption、WebDisplayOption,前者适用于C/S程序,后者适用于B/S程序。

图2-2 正向测试结构图

解释:正向测试的实现并不复杂,在对B/S程序进行全局测试时要传入一个System.Web.UI.Page对象(一般是当前页),用来保存TestRunner到session。如果需要显示测试进度还要传入一个用于反馈进度的URL地址,简单说就是LPTF会提供一个aspx文件,实际使用时可以将其放到当前项目中编译,在运行时把这个文件对应的URL作为TestRunner的构造参数即可。

StraightTest的具体执行顺序大致是“生成TestRunner对象→调用TestRunner的RunTests方法启动测试→调用TestRunner的PhaseEnd方法结束一个阶段的测试→…→调用TestRunner的End方法结束测试”。每一次PhaseEnd和最后的End方法都会记录当前的测试结果,测试结束后可调用GetTestResult方法获取全部测试结果。测试结果记录每个阶段的名称和相应的执行时间。

图2-3 反向测试结构图

解释:反向测试比正向测试要复杂一些,主要是针对同一段程序要准备不同的执行程序(这里称之为测试用例TestCase,一般分“长时间-Max”、“中等时间-Median”、“短时间-Min”三个测试环境)。如果每个测试用例要进行一些初始、扫尾和验证动作,则还要把相应的方法委托给PreTestCleanup、PostTestCleanup和TestValidityCheck。测试执行器会根据整体测试情况计算出一个一般运算时间值(这里称之为规范值NormalisedTimeSpan)。

反向测试的执行过程是首先开辟一个单独的线程,根据指定的执行次数和迭代次数执行用例。执行用例的顺序是随机的。最后,筛选并统计每个用例的执行时间。

另外,反向测试中的测试进度(Progress)直接写在了LPTF中,这是因为反向测试的测试程序都是C/S程序,不存在URL的问题,可以直接写成dll。

图2-4 测试结果输出引擎结构

解释: LPTF提供了丰富的输出格式。通过一个抽象类output规范了统一接口,各种输出方式继承output并实现OutputResults方法,output还提供了一个DisplayResults方法动态调用具体的输出方法。由于正向测试和反向测试的测试结果形式不同,在ChartOutputForm中提供了一个属性IsDisplayReverseTest用于指定是否显示反向测试结果。对于WebChartOutput类,因为会有显示图表控件、URL、编译等问题,最好由用户在自己的应用程序中实现。

3 使用示例

下面是后面部分示例中会用到的一段程序。

//被测试程序

private UInt16 _mediumFactor, _maxFactor;

public UInt16 MediumFactor

{

get {return _mediumFactor;}

set {_mediumFactor = value;}

}

public UInt16 MaxFactor

{

get {return _maxFactor;}

set {_maxFactor = value;}

}

public void FastMethod(Int32 NumberIterations)

{

int j = 0;

for (int i = 0;i < NumberIterations;++i)

{

j += i;

}

}

public void MediumMethod(Int32 NumberIterations)

{

int j = 0;

for (int i = 0;i < NumberIterations;++i)

{

for (int k = 0; k < _mediumFactor; ++k)

j += k;

}

}

public void SlowMethod(Int32 NumberIterations)

{

int j = 0;

for (int i = 0;i < NumberIterations;++i)

{

for (int k = 0; k < _maxFactor; ++k)

j += k;

}

}

□ 正向测试

首先来看C/S程序的正向测试,

public DotNetPerformance.StraightTest.TestResult[] RunSTest()

{

const int numberIterations = 50000000;

DotNetPerformance.StraightTest.TestRunner tr = new DotNetPerformance.StraightTest.TestRunner();

tr.RunTests();

FastMethod(numberIterations);

tr.PhaseEnd("Phase1");

MediumMethod(numberIterations);

tr.PhaseEnd("Phase2");

SlowMethod(numberIterations);

tr.End("最后一个阶段");

return tr.GetTestResult();

}

private void btnST_Click(object sender, System.EventArgs e)

{

DotNetPerformance.ResultOutput.Output.DisplayResults(RunSTest(),

DotNetPerformance.ResultOutput.DisplayOption.Chart,null);

}

图 3-1 正向测试结果-图形输出

再来看B/S程序单个页面里的正向测试(这里用System.Threading.Thread.Sleep来模拟一段程序的执行),在结果输出时要传入页面对象用于注册脚本,从而显示输出测试结果。

m_Tester = new DotNetPerformance.StraightTest.TestRunner();

m_Tester.RunTests();

System.Threading.Thread.Sleep(1000);

m_Tester.PhaseEnd("第一阶段");

System.Threading.Thread.Sleep(100);

m_Tester.PhaseEnd("第二阶段");

System.Threading.Thread.Sleep(2000);

m_Tester.PhaseEnd("第三阶段");

System.Threading.Thread.Sleep(50);

m_Tester.PhaseEnd("第四阶段");

System.Threading.Thread.Sleep(50);

m_Tester.End("第五阶段");

WebDisplayOption _wdo = UIHelper.ToWebDisplayOption(this.ddlOutputMode.SelectedValue);

if(_wdo == WebDisplayOption.WebAlert)

{

DotNetPerformance.ResultOutput.Output.DisplayResults(m_Tester.GetTestResult(),_wdo,new object[]{this.Page});

}

else if(_wdo == WebDisplayOption.WebTable)

{

DotNetPerformance.ResultOutput.Output.DisplayResults(m_Tester.GetTestResult(),_wdo,new object[]{"",this.Page});

}

else if(_wdo == WebDisplayOption.WebXml)

{

DotNetPerformance.ResultOutput.Output.DisplayResults(m_Tester.GetTestResult(),_wdo,new object[]{"",this.Page});

}

else

{

//

}

图 3-2正向测试结果-Web提示输出

对于B/S多个页面间的测试,需要用GlobalStraightTest。如果要显示测试进度还要传入一个URL(前面已解释)。

DotNetPerformance.StraightTest.GlobalStraightTest.WebContainerPage = this.Page;

DotNetPerformance.StraightTest.GlobalStraightTest.RunTests("http://localhost/LPTDemo/WaitPage.aspx");

System.Threading.Thread.Sleep(1000);

DotNetPerformance.StraightTest.GlobalStraightTest.PhaseEnd("第一个页面阶段1");

System.Threading.Thread.Sleep(100);

DotNetPerformance.StraightTest.GlobalStraightTest.PhaseEnd("第一个页面阶段2");

图 3-3 正向全局测试-进度条1

下面转到第二个页面,

Response.Redirect("MidWebForm.aspx");

DotNetPerformance.StraightTest.GlobalStraightTest.WebContainerPage = this.Page;

System.Threading.Thread.Sleep(50);

DotNetPerformance.StraightTest.GlobalStraightTest.PhaseEnd("第二个页面测试结束");

Response.Redirect("EndWebForm.aspx");

图 3-4 正向全局测试-进度条2

第三个页面,

System.Threading.Thread.Sleep(150);

DotNetPerformance.StraightTest.GlobalStraightTest.End("第三个页面测试结束");

WebDisplayOption _wdo = UIHelper.ToWebDisplayOption(this.ddlOutputMode.SelectedValue);

if(_wdo == WebDisplayOption.WebAlert)

{

DotNetPerformance.ResultOutput.Output.DisplayResults(

DotNetPerformance.StraightTest.GlobalStraightTest.GetTestResult(),_wdo,new object[]{this.Page});

}

else if(_wdo == WebDisplayOption.WebTable)

{

DotNetPerformance.ResultOutput.Output.DisplayResults(

DotNetPerformance.StraightTest.GlobalStraightTest.GetTestResult(),_wdo,new object[]{"",this.Page});

}

else if(_wdo == WebDisplayOption.WebXml)

{

DotNetPerformance.ResultOutput.Output.DisplayResults(

DotNetPerformance.StraightTest.GlobalStraightTest.GetTestResult(),_wdo,new object[]{"",this.Page});

}

else

{

//

}

图 3-5 正向全局测试结果-XML输出

图 3-6 正向测试结果-Web表格输出

图 3-7 正向测试结果-Web图形输出

□ 反向测试

/// <summary>

/// 测试主调函数

/// </summary>

/// <returns></returns>

public DotNetPerformance.ReverseTest.TestResult[] RunTest()

{

const int numberIterations = 50000000;

const int numberTestRuns = 5;

DotNetPerformance.ReverseTest.TestRunner tr = new DotNetPerformance.ReverseTest.TestRunner(numberIterations,

numberTestRuns);

DotNetPerformance.ReverseTest.TestRunner.TestCase testCases = null;

testCases +=

new DotNetPerformance.ReverseTest.TestRunner.TestCase(this.FastMethod);

testCases +=

new DotNetPerformance.ReverseTest.TestRunner.TestCase(this.MediumMethod);

testCases +=

new DotNetPerformance.ReverseTest.TestRunner.TestCase(this.SlowMethod);

return tr.RunTests(testCases);

}

/// <summary>

/// 触发测试并将得到的结果输出

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnTest_Click(object sender, System.EventArgs e)

{

DotNetPerformance.ResultOutput.Output.DisplayResults(RunTest(),

DotNetPerformance.ResultOutput.DisplayOption.Chart,null);

}

图 3-8 反向测试结果-图形输出1

图 3-9 反向测试结果-图形输出2

4 结论

总的来说,LPTF基于实际应用中测试需求,提供了一个比较全面的轻量级性能测试框架。与文[1]所给框架相比,LPTF整合了更强的实时进度提示、远程测试、弹性结果输出接口等。

当然,还是存在一些不足。比如反向测试脚本编写麻烦、进度条显示用到依赖于浏览器设置的XMLHttpRequest技术等。

Reference:

[1] Nick Wienhol. Performance Measurement Framework for .NET.

http://www.dotnetperformance.com/default.aspx

[2] Adam Slosarski. NTime - Performance unit testing tool.

http://www.codeproject.com/dotnet/NTime.asp

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有