J2EE开发平台的软件测试技术
作者:佚名(来自:cybercorlin.net)
前言 - 以测试为导向的软件开发流程
软件开发流程的新兴观念是将软件测试的角色,提升为系统开发时每一个阶段都必须要持续且反复进行的重要任务,确保每一个阶段都能及早发现潜藏于系统内的危险因子。当某一个阶段的测试结果无法达到预期的要求时,就必须回溯到之前的开发阶段,再次分析和审核,这种过程称之为重构(Refactoring)。配合重构的机制,让系统的品质都能够在严密的测试监控下持续成长。不过由于网络时代的革命兴起之后,软件系统的架构变得更为复杂,相对的
软件测试的发展也更显得重要。
J2EE平台内的
软件测试
XP只定义了两种测试的层级,第一种层级是「
单元测试」,因为
单元测试的用意是为了检验程序代码是否合乎逻辑,而且是针对系统内部的模块来测试,因此又可以称做为程序逻辑测试(Code Logic Testing)。为了因应不同的应用程序开发平台的特殊架构,在J2EE的平台里,还发展出与J2EE Container 紧密结合的整合测试(Integration Testing)。
另一种层级是接受度测试(Acceptance Testing),又称作
功能测试(Functional Testing)。在软件测试中还有一个大家常听到的是效能测试(Performance Testing)。由于效能测试与客户的需求是密不可分,所以将它归类为接受度测试的延伸应用。最后归纳起来,一个J2EE平台可能所需要的
测试流程,以及测试之间的关系,如图一所示。
在Web层内
软件测试的概念与流程,如图二所示,其中键头旁的数字符号代表着整个
测试流程的执行步骤。首先先准备好受测数据与受测系统之后,借着虚拟浏览器来发出request,向受测系统取得包裹着HTML code的response。然后再利用测试平台来协助我们进行受测数据与预期值的比对工作。当比对后所回报的结果都是正确无误时,代表着受测系统的功能可以正常运作了。图中的测试平台与虚拟浏览器在测试中扮演着关键的角色。
虽然发展测试平台的概念已经行之有年了,然而具备有可延伸且开放式架构的测试平台并不多,其中OpenSource社群以Java开发出来的JUnit,是极具代表性的测试平台。
1. 单元测试平台─ JUnit
JUnit平台的设计架构是采用了命令(Command)和复合(Composite)两种设计模式(Design Pattern)做为关键的组成架构。在JUnit平台中的核心类别是TestCase,而每一个TestCase代表着一个命令对象。TestCase包含数个test method,用来测试被测类别内public method的产出对象与预期的结果是否相同。在JUnit平台内有提供数种用来协助比对的assert method。
JUnit平台里还有另一个核心类别是TestSuite,而每一个TestSuite代表着一个复合的对象。一个TestSuite可以由数个TestCase或是数个TestSuite组成,因此可以根据测试的需求,拼凑出多个的TestSuite。整个JUnit测试平台的组成架构,如图三所示。在了解了JUnit平台的架构之后,我们便可以运用JUnit平台来发展受测系统的整合测试与功能测试。
代码实例: import junit.framework.*; import java.util.Vector; public class VectorTest extends TestCase { protected Vector fEmpty; protected Vector fFull; public VectorTest(String name) { super(name); } public static void main (String[] args) { junit.textui.TestRunner.run (suite()); } protected void setUp() { fEmpty= new Vector(); fFull= new Vector(); fFull.addElement(new Integer(1)); fFull.addElement(new Integer(2)); fFull.addElement(new Integer(3)); } public static Test suite() { return new TestSuite(VectorTest.class); } public void testCapacity() { int size= fFull.size(); for (int i= 0; i < 100; i++) fFull.addElement(new Integer(i)); assertTrue(fFull.size() == 100+size); } public void testClone() { Vector clone= (Vector)fFull.clone(); assertTrue(clone.size() == fFull.size()); assertTrue(clone.contains(new Integer(1))); } public void testContains() { assertTrue(fFull.contains(new Integer(1))); assertTrue(!fEmpty.contains(new Integer(1))); } public void testElementAt() { Integer i= (Integer)fFull.elementAt(0); assertTrue(i.intValue() == 1); try { Integer j= (Integer)fFull.elementAt(fFull.size()); } catch (ArrayIndexOutOfBoundsException e) { return; } fail("Should raise an ArrayIndexOutOfBoundsException"); } public void testRemoveAll() { fFull.removeAllElements(); fEmpty.removeAllElements(); assertTrue(fFull.isEmpty()); assertTrue(fEmpty.isEmpty()); } public void testRemoveElement() { fFull.removeElement(new Integer(3)); assertTrue(!fFull.contains(new Integer(3)) ); } } import junit.framework.*; import junit.runner.BaseTestRunner; public class AllTests { public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } public static Test suite() { TestSuite suite= new TestSuite("Framework Tests"); suite.addTestSuite(ExtensionTest.class); suite.addTestSuite(TestCaseTest.class); suite.addTest(SuiteTest.suite()); suite.addTestSuite(ExceptionTestCaseTest.class); suite.addTestSuite(TestListenerTest.class); suite.addTestSuite(ActiveTestTest.class); suite.addTestSuite(AssertTest.class); suite.addTestSuite(StackFilterTest.class); suite.addTestSuite(SorterTest.class); suite.addTestSuite(RepeatedTestTest.class); suite.addTestSuite(TestImplementorTest.class); if (!BaseTestRunner.inVAJava()) { suite.addTestSuite(TextRunnerTest.class); if (!isJDK11()) suite.addTest(new TestSuite(TestCaseClassLoaderTest.class)); } return suite; } static boolean isJDK11() { String version= System.getProperty("java.version"); return version.startsWith("1.1"); } }
|
2 整合测试的观念与Cactus应用
整合测试提供了J2EE Container的环境,可以快速轻易地检验出Domain Object与J2EE Container的互动行为是否合乎逻辑。因此整合测试的对象是以一个EJB、Servlet或是JSP的程序代码为基本单元。Open Source社群的Jakarta计划中的子计划Cactus,即是为了实作整合测试用的平台而诞生的。
Cactus基本上也是延伸JUnit平台而发展出来的,因此它除了原有基本的method之外,还提供了可以用来模拟浏览器的内部行为的beingxxx( )和endxxx( )的method。这两个method来这些method的执行顺序和与Web Container互动的行为模式,如图四所示。
我们利用beginxxx( )来设定要传递给受测对象的字符串参数。执行完beginxxx( )后,会发出request将参数名称与参数值传递到Web Container。TestCase会执行setUp( ),将受测对象所需要的对象环境建立起来,接着在testxxx( )执行存取受测对象的动作。当存取受测对象的动作执行完后,便可以检验受测对象可能存放在session的产出物。然后在Web Container会执行释放资源的动作,然后将response回传到Client端。最后在Client端执行endxxx( )来进行比对HTML code是否和预期值相同,执行完endxxx()时也代表一个整合测试的结束。将这五个method所执行的功能汇整如表一所示。
虽然Cactus架构提供了受测对象产出物与预期结果的比对功能,但是当回传的HTML code的内容过于庞大复杂时,反而不利于比对的工作。因此采用了一个实用性的做法。此做法是在JSP或servlet欲产出的HTML code的程序代码里,于关键的卷标内添加ID这种属性。当endxxx( )要进行比对前,先读取记载着ID属性值与预期值的外部数据文件,再透过DOM的存取机制来取得HTML code,便能够快速地比对关键的数据。不仅可以将比对的工作模块化,更能够在不需要重新编译测试码的情形下,随时变更预期值。读者们若有遇到相似的问题时,不妨可以采用与相同的策略来解决。
整合测试不同于
单元测试,虽然减低了撰写测试码的困难度,但也因为Domain Object与J2EE Container的结合,而不能为Domain Object提供单纯的测试环境。因此若有其它的测试可以单纯地检验整个系统,便可以弥补整合测试的不足。
功能测试即是扮演这样的一个角色。
配置信息与代码实例:
<servlet> <servlet-name>ServletRedirector</servlet-name> <servlet-class> org.apache.cactus.server.ServletTestRedirector </servlet-class> <init-param> <param-name>param1</param-name> <param-value>value1 used for testing</param-value> </init-param> </servlet> <servlet> <servlet-name>ServletTestRunner</servlet-name> <servlet-class> org.apache.cactus.server.runner.ServletTestRunner </servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletRedirector</servlet-name> <url-pattern>/ServletRedirector</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ServletTestRunner</servlet-name> <url-pattern>/ServletTestRunner</url-pattern> </servlet-mapping> 实例testcase: import junit.framework.Test; import junit.framework.TestSuite; import org.apache.cactus.ServletTestCase; import org.apache.cactus.WebRequest; public class TestSampleServlet extends ServletTestCase { public TestSampleServlet(String theName) { super(theName); } public static Test suite() { return new TestSuite(TestSampleServlet.class); } public void beginSaveToSessionOK(WebRequest webRequest) { webRequest.addParameter("testparam", "it works!"); } public void testSaveToSessionOK() { SampleServlet servlet = new SampleServlet(); servlet.saveToSession(request); assertEquals("it works!", session.getAttribute("testAttribute")); } }
|
3 业务逻辑测试与StrutsTestcase应用
struts的使用越来越广泛,但是并没有合适
测试框架与之对应.cactus, httpunit虽然都可以测试jsp,servlet,但基于struts框架的应用程序的测试依然比较麻烦。
不过,StrutsTestCase的出现多少解决了些问题,下面主要讲讲StrutsTestCase的应用。和其他的JSP/SERVLET
测试框架一样,StrutsTestCase也有两种测试结构,一种是Mock结构,另一种是利用Cactus的结构。
因为StrutsTestCase也是基于junit上开发的,所以它的使用方法也类似于junit.可以参考他的例子和api.
可惜的是StrutsTestCase例子里没有使用ant,因此它的运行较让人头痛,特别是有关配置文件的处理。StrutsTestCase在运行时必须能够找到struts-config.xml和web.xml文件,默认的位置是web-inf/目录下,所以web-inf目录要存在于classpath或者在运行的时候指定。例如:我的位于d:/struts-test/下,struts-config.xml和web.xml位于d:/struts-test/webapp/WEB-INF/下,那么在运行测试的时候应当把d:/struts-test/webapp路径放到classpath里。如果我的struts-config.xml不在/web-inf目录里,而是在/web-inf/conf/目录下,那么就须调用setConfigFile(String path)方法,按照刚才的情况,
public void testSuccessfulLogin() { setRequestPathInfo("/login"); addRequestParameter("username","deryl"); addRequestParameter("password","radar"); actionPerform(); verifyForward("success"); } public void testFailedLogin() { addRequestParameter("username","deryl"); addRequestParameter("password","express"); setRequestPathInfo("/login"); actionPerform(); verifyForward("login"); } public void setUp() throws Exception { super.setUp() ; setConfigFile("/WEB-INF/conf/struts-config.xml") ; }
|
4 功能测试的观念与HttpUnit应用
以UML的术语来说,
功能测试的对象是检验Use Case所规范的行为,测试系统是否符合所需要的功能,是否能达到使用者的需求?而单元测试的对象是检验对象Classes Diagram与Sequence Diagram所描述的关系与行为,测试单元是否执行正确,是否符合程序逻辑?。每当完成一个阶段性的
功能测试,也代表着完成了一部分的系统实作。
Open Source社群的HttpUnit API套件,即是为了功能测试而发展出来的。HttpUnit是以Java撰写出来的虚拟浏览器,用来模拟浏览器的内部行为。前一节所提到的Cactus检验HTML code的机制,也是采用HttpUnit来完成的。
除此之外,HttpUnit还可以结合JUnit平台撰写测试码来检验回传的网页内容是否与预期结果相符合。HttpUnit平台的运作机制是建构在Http标准通讯协议之下,藉由模拟使用者浏览网站时,所发出的以对象的形式封装的request讯号,将其送至到目的网站,然后等到该网站处理完此request之后,便将同样以对象形式封装的response讯号回传给HttpUnit。
由于HttpUnit所接收的是标准HTTP协议的response对象,因此不论该网站是静态网页语言或是用任何的动态服务器端语言写成的,都可以透过HttpUnit来模拟网站浏览的行为并且取得标准的HTML code。
市面上也有提供
功能测试用的预录播放软件,可以事先录下网站浏览的步骤,然后反复地播放预录好的流程,最后回报测试的数据给测试人员,供测试人员进行分析,大大节省撰写测试码的负担。然而此类软件有以下的缺点:
1. 当网站设计的复杂度越高,浏览的分支流程越多,预录好的流程便无法作有效的模块化管理。
2. 预录播放软件虽然有提供记录浏览步骤的script或是XML文件,虽然这些指令码可以重复利用,然而若无法提供有效的侦错机制,一旦安插了错误的程序,反而容易造成无法预期的错误产生。
3. 测试人员需要重新学习专属于预录播放软件的script语言或是XML文件语法,无法从既有熟悉的程序语言来编写浏览网站的程序。
4. 当网站的操作接口时常为了需求而新增或是修改原有的互动设计时,必须重新录制新的浏览网站的程序,而无法重复利用。
HttpUnit解决了软件开发人员以上的困扰。HttpUnit是一种黑箱作业形式的
测试工具,因此我们只要专注如何在JUnit平台上撰写模拟浏览器行为的测试码即可。HttpUnit内的method执行顺序和与Web Container互动的行为模式,如图五所示,箭头符号旁所标示的数字,代表着这些method的执行顺序。
当我们在setup( )设定好受测的网址与相关的环境后,setUp( )会执行向受测网址进行存取的动作。当存取动作完成时,会将response回传至Client端。此时可以在testxxx( )做HTML code和预期值比对的工作。最后在Client端执行释放资源的动作,执行完tearDown()时也代表一个
功能测试的完成。将这三个method所执行的功能汇整如表二所示。
虽然HttpUnit提供强大的仿真功能,但是HttpUnit本身还是存在两个缺点。第一,当HttpUnit结合JUnit平台做测试时,由于HttpUnit存取HTML code的方式与HTML内部的文件结构的关联过于紧密,因此当网页版面需要变动时,也需要修改相对应的测试码。对于这样的困扰,采用了与Cactus检测HTML code同样的改良策略,来达到快速比对而不用调整测试码的好处。
第二,在HttpUnit与JUnit平台结合做测试的情况时,由于JUnit特殊的运作机制,无法记住每一个已经浏览过的网址状态,因此当某个受测网址与其它网址的依存性强时,若要回传正确的浏览状态时,必须要用递归记忆的方式来达成。例如要存取第二个网页必须记住第一个网页的状态,存取第三个网页要记住第一个和第二个网页的状态,同理存取第n个网页时需要记住第一个网页到n-1个网页,这样的做法不易将测试码模块化,如图六所示。
于是利用了HttpUnit本身也可以写成独立运作的程序代码的特性,写成一个浏览网站步骤的仿真器。然后利用JUnit的setUp( )来存取受测网站的浏览状态,便可以在testxxx( )取得正确的网页状态来进行比对的工作,经过模块化后的HttpUnit测试架构如图七所示。
5 可以参考的测试项目:
Junit 包中有比较简单的测试用例的例子。
Eclipse 开发平台的 JUnit Plugin Tests and Automated Testing Framework 插件中的JunitTest项目例子,比较详细的介绍了junit测试平台。
参考文献
1. JUnit官方网站http://www.junit.org/index.htm
2. Cactus官方网站http://jakarta.apache.org/cactus/index.html
3. Strutstestcase网站http://strutstestcase.sourceforge.net/
4. HttpUnit 网站 http://sourceforge.net/projects/httpunit/
5. Eclipse 网站
http://www.eclipse.org/downloads/index.php
分享到:
相关推荐
本文将深入探讨软件测试技术在J2EE项目中的应用,以及在不同测试阶段中常用的测试工具。 J2EE是一种用于构建企业级分布式应用程序的平台,其复杂性和规模要求严谨的测试策略来确保系统的稳定性和可靠性。测试过程...
**华丹 CHARISMA 智能 WEB 平台**是一款专为J2EE环境设计的快速开发平台,旨在简化Web应用的开发流程,提高开发效率,并能够支持复杂的业务系统和报表功能。这款平台不仅可以用于快速构建各类业务系统,还可以作为...
在企业级软件开发中,J2EE(Java 2 Platform, Enterprise Edition)是一个至关重要的平台,它为构建可扩展、安全且高度分布式的企业应用程序提供了框架和API。《J2EE企业级应用测试实践》这本书深入探讨了在这个复杂...
【标题】"niit MVC4 j2ee .net 软件测试"涵盖了多个关键的IT技术领域,包括Java企业版(J2EE)、Microsoft的.NET Framework以及软件测试的实践。这些主题对于理解和开发现代企业级应用至关重要。 **1. J2EE(Java...
9.4 基于J2EE平台的测试 9.5 其他应用服务器应用的测试 4 9 第10章 软件本地化测试 10.1什么是软件本地化 10.2软件本地化的翻译问题 10.3软件本地化测试的技术问题 10.4本地化测试的重点 2 10 第11章 软件测试自动化...
Java及J2EE平台技术是IT领域中至关重要的组成部分,尤其在企业级应用开发中扮演着核心角色。本文将深入探讨这两个技术领域的关键知识点。 首先,Java平台是基于Java编程语言的一个全面的软件开发和运行环境。它由三...
对于J2EE开发,Eclipse的Enterprise Edition(Eclipse IDE for Java EE Developers)是个不错的选择。 3. **Application Server**:如Tomcat、GlassFish、JBoss或WebLogic,它们为运行J2EE应用程序提供了一个容器。...
性能测试是软件测试的一个分支,主要目的是评估软件产品的性能,包括速度、稳定性、可靠性和资源消耗等指标。J2EE性能测试就是针对运行在J2EE平台上的应用软件进行性能测试。为了确保J2EE应用能够高效、稳定地运行,...
在IT领域,特别是软件开发行业中,Java 2 Platform, Enterprise Edition(简称J2EE)是一个极为重要的技术框架,专门用于构建可扩展、健壮的企业级Web应用。《Designing Enterprise Applications with the Java 2 ...
《J2EE开发技术手册》是一本专门为IT专业人士编写的指南,旨在提供全面且实用的J2EE(Java 2 Platform, Enterprise Edition)开发知识。J2EE是Oracle公司推出的企业级Java应用平台,用于构建分布式、多层的Web应用...
软件测试方法和技术 共17章 1.1 软件的含义 1.2 软件开发过程的特性 1.3 软件测试的重要性 2.1 软件质量就是客户的满意度 2.2 软件缺陷(Bug)是什么 2.3 软件测试的基本方法 2.4 软件测试的分类和阶段 2.5 软件测试...
软件测试方法和技术,共17章 1.1 软件的含义 1.2 软件开发过程的特性 1.3 软件测试的重要性 2.1 软件质量就是客户的满意度 2.2 软件缺陷(Bug)是什么 2.3 软件测试的基本方法 2.4 软件测试的分类和阶段 2.5 软件测试...
在J2EE开发中,构建一个合适的开发环境是至关重要的,本配置手册主要涉及的软件包括数据库SQL Server 2000、JDK、服务器Tomcat以及IDE Eclipse和MyEclipse。以下是详细配置步骤: 1. **数据库安装** - **SQL ...
1. 复杂性:由于其采用了众多的技术和协议,学习和掌握J2EE开发需要较高的成本。 2. 性能开销:相对于某些其他架构,J2EE在性能上可能存在一定的开销,尤其是在高并发场景下。 3. 学习曲线:由于J2EE涉及的技术和...
《J2EE开发手册大全》是一份全面涵盖J2EE技术开发的综合资源,旨在为开发者提供详尽的离线参考指南。这份手册包含了从基础概念到高级实践的所有关键知识点,帮助开发者在没有网络的情况下也能深入理解和应用J2EE技术...