随着开发软件往可复用服务的迁移,很多软件开发生命周期中的范式被开发了出来。正如面向对象要求一个非凡的概念集合来达到有效的开发,面向对象架构也带来了它共享的具体途径。在接下来的段落中,我们将会我们将会探索开发服务的许多重要方面中的一个:测试。
依靠于你们组织中的软件治理类型,测试可以通常作为一个全局过程或者最高优先权的过程。以前的方法,在代码行之间用灵敏开发技巧,强迫把测试推迟到服务被完全实现以后才进行测试,而随后的服务就会采用这个还没有经过测试的服务,并且不等到你使之成为一个“预备好”的服务。
当有支持者确认了一个调查,在开始就 进行测试并且采用灵敏原则比直到最后的开发阶段才测试更有好处,我们暂且不管这些,我们先把关于何时把测试引入到你具体的工程中去的讨论搁置一边,让我们关注一下如何进行测试。
测试决不是一个简单的东西,有很多不同的测试类型可以应用在软件上。依据测试的复杂性和领域 ,即使专业的团队——QA团队——可以被雇来完成特定的任务,但是是为了特定的目定,我们将会关注两种类型的测试,他们都相对轻易的开发:单元测试和压力测试。
单元测试是指通过预先定义的一些列数据集合来验证一个服务的既定目的的过程,这个数据集合是用来模拟显示世界的用法从而能够及时的方式来探测到缺陷。当为你的服务进行单元测试的时候, 在服务被发布为正是的产品以前你可以把他们看成安全保护网,因为你能够在实际数据流在这个系统运行之前使用这些预先的数据集合来测试你的服务的逻辑。
另外一个单元测试为你的开发带来的那些好处在当你的系统开始用上了一段时间之后就会更加突出了。因为演化的服务意味着底层逻辑的修改,这些修改可能会破坏服务本来被希望忙足的一些具体的使用设定。尽管如此,通过现有的单元测试套件,并且保证一直保持同这些测试的一致,保护任何使用你服务的依靠部分免受在以后可能新的修订中带来的任何破坏
实际的单元测试的进行很大程度上依靠于编程语言或者你使用来部署你的服务的平台,但是更加可能的情况是为了能更轻易的进行测试的步步为营,确认和部署,将会通过一个特定的框架来完成这些 ——换一句话说就是, 自动化的进行所有的能够使得单元测试成为必需的过程。
在所有的最流行的单元测试的框架中有:java的JUnit 和.NET的Unit Testing Framework ,Unit Testing Framework 构成了Visual Studio的一部分。对于深度的解释他们的框架或者其他的一些单元测试套件将不会在本文中讨论,但是列表1.1展示的就是一个Java支持的服务的Junit测试是怎样的。
列表1.1 对Java类构成的Web Services的Junit单元测试
import junit.framework.*;
public class PayrollTest extends TestCase {
PRivate Payroll basePayroll;
private Employee accountingE;
public PayrollTest(String type) {
super(type);
}
protected void setUp() {
// Initialize Payroll object
basePayroll = new Payroll();
// Generate employee, assign to payroll
accountingE = new Employee("John Smith", 5743.00);
basePayroll.addEmployee(accountingE);
}
protected void tearDown() {
// Reinitialize Payroll object
basePayroll = null;
}
public void testAddEmployee() {
Employee contractE = new Employee("Auditor", 2843.00);
basePayroll.addEmployee(contractE);
double totalPayroll = accountingE.getSalary() + contractE.getSalary();
assertEquals(totalPayroll, basePayroll.getTotal(), 0.0);
assertEquals(2, basePayroll.countEmployees());
}
public void testEmptyPayroll() {
basePayroll.emptyPayroll();
assertTrue(basePayroll.emptyPayroll());
}
public void testEliminateEmployee() throws EmployeeNotFound {
basePayroll.eliminateEmployee(accountingE);
assertEquals(0, basePayroll.countEmployees());
assertEquals(0.0, basePayroll.getTotal(), 0.0);
}
public static Test suite() {
TestSuite suite = new TestSuite(PayrollTest.class);
return suite;
}
public static void main(String args[]) {
junit.textui.TestRunner.run(suite());
}
}
这个测试列表表示的是对两个将会用来构成决定薪水册的数据的Web service进行测试的一个例子。请注重Payroll和Employee类的实例是如何创建的,它们都会被后面的testXXX()命名的方法来操纵。一旦被这些方法操作,请注重看到是通过不同的以assertXXX()命名的Junit方法来调用的。
用来调用预先定义的数据块的不同的断言方法的参数在底层的服务类之间传递,在这些类上进行同所期望的值进行比对,这个比对是在当测试框架给出一个错误或者返回一个正确的执行的时候进行。
单元测试是用来验证一个服务逻辑的完整性,重点测试是用来决定一个服务在一个特定的用户附载的时候应该具有什么样的行为,它是一个可以帮助决定对一个服务的基础架构的适当支持的过程,这些基础架构包括如硬件能力,应用程序配置和可以获得的网络带宽,以及其他的东西。
一个可以帮助你进行压力测试的工具是JMeter ,它是一个由Apache组织开发的一个开源项目。尽管Jmeter是基于java的,它可以产生SOAP和xmlRPC类型的请求,有效地发挥一个Web services客户端的功能,来压力测试任何服务端的部署。图1.1展示的是一个使用这个工具进行的在SOAP/XML-RPC服务上的附载测试。
图1.1:Jmeter对Web services的压力测试
在Jmeter中创建上述的压力测试的过程如下:
1. 在Jmeter的主界面,将你的鼠标移动到Test Plan按钮上并点击右键。从弹出的菜单中选择:Add – Thread Group。Thread Group按钮将会被创建。
2.定位在Thread Group按钮上左边的窗体中将会显示不同的参数。参数Number of threads 表示的是你的压力测试将会对你的服务仿效的请求的数。
3.下一步,当鼠标在Thread Group按钮上点击右键,从弹出的菜单中选择:Add – Sampler – SOAP/XML-RPC Request。SOAP/XML-RPC请求按钮将会被创建。
4.鼠标定位在SOAP/XML-RPC请求按钮,左边的窗体中将会显示不同的参数。有关于你的Web service的URL的介绍,以及你希望发出的每一个请求的载荷。
5.当鼠标在SOAP/XML-RPC请求按钮上时,点击右键,从弹出的菜单中选择:Add – Listener – Monitor Results,和Add – Listener – View Results。两个显示压力测试结果的按钮将会生成。注重:假如需要,你可以添加更多的监听者,这是Jmeter进行压力测试结果的表示术语。
6.保存你的测试,并从最高层的菜单中选择Run-Start选项开始你的压力测试。
7.最后移动你的鼠标到每一个不同的Listener按钮上, 观察你在对你的Web service进行压力测试时获得的性能参数。
和单元测试框架相类似的本质,解释Jmeter的许多复杂——或者任何其他压力测试工具的这方面的问题——将会超出本文的范围,但是Jmeter提供了全面可理解的并可自由获取的文档来解释不同的压力测试功能。
我们总结我们对在Web services环境下单元测试和压力测试的熟悉,这是在很多的测试过程中你可以在你的面向服务设计中的两个方法,从而能够确保你的部署的完整性和可测量性。