赵卫东 彭偲
摘 要: 单元测试是软件测试中的最底层的一种测试活动,是软件开发中不可忽视的一个环节,但我国高校软件单元测试的教学效果并不理想。本文分析了传统实验教学存在的问题,引入先进流行的开源测试框架,设计了单元测试实验课程教学内容;采用任务驱动教学方法,以理论知识为基础,以企业需求为标杆,对实验教学方法进行了改革,收到了良好的教学效果。
关键词: 单元测试教学;软件开发;实验课程;JUnit
中图分类号: TP311.56; G712 文献标识码: A DOI:10.3969/j.issn.1003-6970.2019.07.042
【Abstract】: Unit testing is the lowest level of testing activities in software testing. It is a link that cannot be ignored in software development. However, the teaching effect of software unit testing in Chinese universities is not ideal. This paper analyzes the problems existing in traditional experimental teaching, introduces the advanced and popular open source testing framework, and designs the teaching content of the unit test experiment course. It adopts the task-driven teaching method, based on the theoretical knowledge, and takes the enterprise demand as the benchmark to carry out the experimental teaching method. The reform received good teaching results.
【Key words】: Unit test teaching; Software development; Experimental lesson; JUnit
0 引言
近年來,随着计算机软件走进社会的各个领域,软件测试的重要性也在不断提高。企业更加重视并且愿意投入更多时间和人力成本在软件测试上[1],因此许多高校也将软件测试设为独立课程,力求为国家和企业培养出更多测试领域的人才。
然而,单元测试的教学效果仍然不尽人意,原因主要有两方面:一方面,单元测试不仅需要专业测试人员,还需要开发者的积极配合和参与。如今部分开发工程师、项目经理仍然怀着传统的观念,认为软件测试是测试工程师的工作,开发工程师不需要参与,甚至认为让开发工程师参与就是“浪费时间”,会影响项目的开发进度[1]。这种观念影响了高校学生,部分学生误认为开发工程师无需学习测试相关知识。学生对测试课程的不重视,使得教学工作开展并不顺利。
另一方面,部分高校的单元测试教学课程设计也不尽合理[3]。主要存在两个问题:一是课程的内容相对陈旧,与软件行业发展的进度严重脱节。部分高校使用的教材或者案例都来自多年前的资料,其技术已经过时或者不适合现在的软件开发。二是缺乏实验课程,学生在课上学到的理论知识无法通过实践来巩固,不仅容易遗忘,而且在日后的工作中也无法得到运用。
为了提高单元测试的教学效果,本文针对这两个方面,设计了一种基于开源测试框架的,任务驱动式单元测试实验课程教学方法,使学生可以更高效的学习单元测试,并有能力将其运用于实际工作或项目中。
1 单元测试框架的选择
1.1 当今流行的单元测试工具
由于单元测试中测试的对象为具体代码段,所以绝大多数的单元测试框架都只能服务于一种特定的开发语言。现在较为流行的几种开发语言为Java语言、C系列语言、Python语言以及JavaScript语言,每种语言都有得到业内认可的单元测试框架。例如,Java语言的JUnit框架,C++语言的GoogleTest框架以及Python语言的unittest框架都是非常优秀的单元测试框架。
1.2 JUnit测试框架的优势
本课程综合分析了多种开发语言和测试框架,最终选择Java语言的JUnit作为教学框架,其原因如下:
(1)Java仍然是使用最广泛的语言。近年来随着智能手机的发展,许多企业都在开发手机App来为用户提供更便捷的服务,而Android系统作为市场份额占有率最高的系统,其主要开发语言就是Java。此外,Java是最常用的服务端开发语言,目前大多数系统的服务端使用Java开发。
(2)JUnit本身功能十分强大,是Java语言中最受欢迎的单元测试框架[2]。传统的单元测试方法是在程序中内嵌代码输出数据,然后再由人工查看来判断程序是否存在问题。这种方式不仅繁琐、代码侵入性高,也可能出现失误。引入了JUnit框架后,利用其断言功能编写相应的测试代码,可以解决上述问题,并且方便进行回归测试。JUnit提供了扩展功能,能让用户自定义断言的方法或者Runner来进行个性化测试[5]。测试完成后,JUnit能帮助用户分析失败原因和定位问题所在。
(3)JUnit拥有良好的生态圈[6]。由于JUnit在Java项目和Android App项目中被广泛使用[7],主流的集成开发环境(例如Eclipse、IDEA和Android Studio)都为JUnit提供了官方插件,用户在这些开发环境中使用起来极为方便。例如,可以一键生成对应的测试报告,或是一键重新测试上一次未通过部分等等。此外,部分常用的Java第三方框架(例如Spring)也为JUnit提供了原生支持。
2 实验内容设计
2.1 实验目的
实验的目的包括以下几点:
(1)掌握在IntelliJ IDEA开发环境中引入开源框架JUnit的方法。
(2)掌握使用JUnit进行单元测试的基本步骤与操作方法。
(3)掌握JUnit的注解功能。
(4)掌握使用JUnit进行参数化测试的方法。
2.2 实验内容
实验的内容主要包括:
(1)使用IntelliJ IDEA创建项目,编写业务逻辑代码作为受测程序。
(2)在IntelliJ IDEA中引入JUnit框架,针对业务代码编写对应的测试代码。
(3)执行测试操作和观察测试结果。
(4)编写多个测试方法,利用集成开发环境提供的功能进行批量测试和回归测试。
(5)理解JUnit的注解功能。
(6)结合理论知识,为一个特定功能单元设计一套完整的测试用例,并学习参数化测试,以便同时测试多个测试用例。
(7)学习打包测试功能,同时测试多个测试类。
2.3 实验教学思路
本实验课程共包含4个学时,分2次授课。授课时不采取传统的先讲后练的模式,而是采用更高效的任务驱动课程的形式[8],将讲解和练习结合在一起。每堂课由数个任务组成,每次讲解并演示完一个任务后,提供足够的练习时间供学生实践,学生在明确任务以后,就开始进行准备工作[9]。
下文将介绍每个任务的实验步骤[10]。
2.3.1 任务一:编写受测程序代码
(1)启动IDEA,新建一个Java項目。
(2)在项目的src文件夹下新建一个计算器类Calculator,作为受测程序。
(3)在Calculator类下添加add、subtract等方法并编写相应代码用于测试,如图1所示。
2.3.2 任务二:引入JUnit并编写测试代码
(1)在项目的根目录下建立一个test文件夹,然后将此文件夹设定为测试源代码目录。
(2)在Calculator类名上右击并依次点击“Go To”和“Test”,在弹出的浮窗中选择“Create New Test”选项。
(3)在弹出的对话框中,点击Fix来添加IDEA内置的JUnit依赖到项目中,在Testing Library中选择JUnit 4,填写类名CalculatorTest,全选要测试的方法并点击确认,如图2所示。
(4)在JUnit生成的模板代码的基础上,利用断言编写测试代码,如图3所示。
2.3.3 任务三:执行单个方法测试和批量方法测试
(1)点击方法名左侧的绿色三角形按钮来进行单个方法的测试。
(2)点击类名左侧的双绿色三角形按钮来进行整个类的批量测试。
(3)观察测试结果,对于未通过的测试,根据JUnit给出的提示来纠正原程序代码,然后通过“执行上一次未通过的测试”功能校验效果。
2.3.4 任务四:利用注解优化代码
(1)在CalculatorTest类新建一个Calculator类的成员变量,并新建一个init方法,在init方法中将其实例化。
(2)在init方法上方添加注解@Before。
(3)去掉测试方法中实例化Calculator的代码,使用成员变量的实例代替,如图4所示。
(4)运行检验是否可以通过,并思考@Before注解的作用。
(5)分别使用@After、@BeforeClass、@AfterClass注解来了解其作用,思考他们的触发时机、顺序和实际用途。
2.3.5 任务五:使用参数化测试来测试多个用例
(1)新建一个ParamAddTest类,并添加@RunWith (Parameterized.class)注解。
(2)在ParamAddTest类下新建三个成员变量input1、input2、output,在构造函数中将其初始化。
(3)按同样的思路编写测试代码,与普通测试不同的是,要将其中的参数对应替换成input1、input2和output。
(4)新建一个data方法用来提供参数,并在此方法加上@Parameters注解,如图5所示。
(5)执行测试,若测试未通过,JUnit会指出导致未通过的测试用例以助于分析原因。
2.3.6 任务六:使用打包测试进行批量类测试
(1)新建一个SuiteTest类。
(2)在SuiteTest类的类名上方添加@RunWith (Suite.class)注解。
(3)在SuiteTest类的类名上方添加@Suite. SuiteClasses({***})注解,其中***部分填写要打包测试的类名,例如@Suite.SuiteClasses({Param AddTest.class, CalculatorTest.class}),如图6所示。
(4)执行测试,若测试未通过,JUnit会指出未通过的测试类以及错误信息。
3 实验教学方法
3.1 传统的教学方法的弊端
相比较其他测试活动而言,单元测试需要开发工程师的参与,甚至是以开发工程师为主体的。大多数企业都比较重视单元测试,部分企业甚至对于单元测试有强制性要求[11]。传统的课程没有强调这一点,使用的技术与教材也相对陈旧,这容易让学生产生“单元测试已经过时”或者“开发者对于测试课程只需了解”的误解,让学生对课程的积极性较低。
正因为单元测试是由开发工程师为主的,所以它更强调实践和编码[12]。传统的教学方法讲述理论知识占用时间比例较大,分配的实验课程时间则较少甚至根本没有。教学内容枯燥,学生积极性不高[13]。这导致了理论与实践相分离,学生无法将学到理论知识进行实际运用,在课后也没有进一步学习的方向,学习效率很低[14]。
3.2 改进的教学方法总结
改进的教学方法更注重于用实验来巩固理论,将二者有机结合在一起,做到不仅能让学生掌握必备的理论知识,还能用代码将其体现出来,直接将学到的知识运用于今后的实习项目或工作中。
教学使用到的前置知识为较基础的必修课程,只需掌握Java基础即能上手,不会使学生丧失学习积极性。随后通过循序渐进的任务式教学,逐步加深课程难度,即使基础薄弱也能跟上节奏;课后提出思考问题,学有余力的学生则能找到课后深入学习的思路和方向,有效的提高了教学效果。
4 实验教学方法展望
改进的实验方法切实有效的提高了教学效果,但是仍然有改进空间。实验中使用了Java作为教学语言,但使用的教学案例相对较基础。调查发现,在学习软件测试课程之前,大部分学生已经学习过较多的编码课程,拥有一定的知识储备和实践能力,可以考虑进一步提高课程深度。
考虑到Java的语言目前主要运用于Android和Web的项目中[15],二者目前對JUnit都有相应的支持。在后续的教学中,可以根据实际情况,将JUnit融入Android或Web项目中进行教学,提高课程深度的同时,与企业需求直接接轨,可更好的提升教学效果。
参考文献
[1] 徐福祯. 计算机软件测试方法及应用实践[J]. 信息与电脑(理论版), 2018(02): 14-16.
[2] 朱冬玲. 基于先进工作过程的软件测试课程教学[J]. 电脑与电信, 2013(11): 33-34.
[3] 陈站华. 软件单元测试[J].无线电通信技术, 2003(05): 50-51.
[4] Vahid Garousi Yusifo?lu, Yasaman Amannejad, Aysu Betin Can. Software test-code engineering: A systematic mapping [J]. Information and Software Technology, 2015, 58.
[5] 白凯, 崔冬华. 基于JUnit自动化单元测试的研究[J]. 计算
机与数字工程, 2010, 38(02): 52-54+103.
[6] Mourad Badri, Fadel Toure,Luc Lamontagne. Predicting Unit Testing Effort Levels of Classes: An Exploratory Study based on Multinomial Logistic Regression Modeling[J]. Procedia Computer Science, 2015, 62.
[7] 刘升贵. 基于MVP模式的Android应用程序实现及其单元测试研究[J]. 福建电脑, 2017, 33(07): 94-95.
[8] 王艳辉. 基于任务驱动的软件测试课程教学模式研究与应用[J]. 济南职业学院学报, 2017(03): 57-58+67.
[9] 周洪茜, 刘丹. 基于思维导图的翻转课堂教学模式研究[J]. 软件, 2018, 39(4): 63-67.
[10] 王芳, 邓一星, 秦映波. 敏捷软件项目管理课程教学方案研究与实践[J]. 软件, 2018, 39(4): 77-81.
[11] 董威. 单元测试及测试工具的研究与应用[J]. 微型电脑应用, 2008(05): 24-26+23+5.
[12] 蔡高亮. 软件单元测试[J]. 信息技术与标准化, 2008(Z1): 41-43.
[13] 闫实, 刘占波, 王晓丽. 云计算技术在高校计算机基础教学中的应用[J]. 软件, 2018, 39(6): 167-169.
[14] 鞠小林, 陈翔, 文万志, 张艳梅. “产教研”融合的软件测试课程案例库构建[J]. 计算机教育, 2019(03): 121-125.
[15] 马金鸣. 计算机软件开发中JAVA编程语言的应用[J]. 电子技术与软件工程, 2017(17): 53.