ScalaTest

ScalaTest 简介

ScalaTest 是一个开源的Java,Scala 的测试框架,它整合了JUnit, TestNG, Ant, and Maven 使你能非常高效,同时又符合你自己需要的单元测试方式。

API :http://www.scalatest.org/scaladoc/doc-1.2/

ScalaTest 单元测试基础

首先看一下ScalaTest 本身提供了哪些测试基类或者特质:

1 )org.scalatest.Suite

只要把测试类扩展Suite ,并且定义了名字以“test ”开头的测试方法,就可以实现简单的测试,参考下面的代码:

 

Java代码   收藏代码
  1.     import org.scalatest.Suite  
  2.    class MySuite extends Suite{  
  3.    def testOk(){  
  4.       assert(true)  
  5.    }  
  6.       def testOther(){  
  7.         assert(true)  
  8.    }  
  9. }  
 

 

testOk() 函数就是为了测试MySuite 这个测试类是否能够跑通,如果想看看测试效果,你可以写个object 中的main方法中new 一个MySuite 对象调用execute() 方法,可以测试所有方法,像这样

    

 

Java代码   收藏代码
  1. (new MySuite).execute()  
 

 

 

这是控制台会打印测试结果,

    Test Starting - MySuite: testOk

Test Succeeded - MySuite: testOk

Test Starting - MySuite: testOther

Test Succeeded - MySuite: testOther

这说明测试成功了。execute() 方法还提供了一个String 参数,传入方法名,作用就是测试特定的方法( 假设MySuite 中含有2 个以上的方法) ,像这样

    

 

Java代码   收藏代码
  1. (new MySuite).execute("testOk")  
 

 

 

ps :在这里会发生版本冲突,如果你的scala.**.jar 的版本是2.8 ,那么scalatest 版本最好是1.2 。经测试,如果不是这样,yoursuite.execute() 方法会失效报异常,必须传入具体方法名才有效。

2 )org.scalatest.FunSuite    (extends Suite )

ScalaTest 提供了名为 FunSuite 的特质,重载了execute ,从而可以让你以函数值的方式而不是方法定义测试:

 

Java代码   收藏代码
  1. import org.scalatest.FunSuite  
  2.     class MyFunSuite extends FunSuite{  
  3.       test("if ok"){  
  4.       assert(true)  
  5.    }  
  6. }  
 

 

FunSuite 的一个好处是你不用给你所有的测试以“test ”开头起名。而且,你可以更容易地给你的测试起很长的名称,因为你不需要把它们编码为驼峰形式。

下面我们再来看看scalatest 提供了哪些断言方法。

 

ScalaTest 断言

1 )assert()

第二节中已经出现这个断言,单参数的assert(condition 表达式) 已经了解,完全类似于JUnit 的assertEqauls(value1,value2) 方法,不过scalatest 为assert() 方法又重载了双参数的方法,其作用就是自定义报错提示,

    assert(condition 表达式,“报错的文本提示”)

如果在condition 表达式中运用“=== ”,那么其作用相当于assert() 双参数方法,但是报错提示是缺省格式的,像这样3 did not equal 2

2 )except()

except() 方法的结构是这样的,except( 期望值){ 比较值} ,报错信息像这样Expected 2, but got 3 ,同样scalatest 为except 提供了类似assert 第二参数的作用,

    except( 期望值,“报错的文本提示”){ 比较值}

3 )intercept()

其作用检查方法是否抛出了期待的异常,其结构是,

    intercept(classOf[ 异常类]){ 会抛异常的表达式}

        和

    intercept(classOf[ 异常类] ,“自定义报错信息”){ 会抛异常的表达式}

如果代码没有抛出异常,或抛出了不同的异常,intercept 将抛出 AssertionError 前者的缺省报错则类似这样,Expected IllegalArgumentException to be thrown, but NegativeArraySizeException was thrown.

4)org.scalatest.matchers.ShouldMatchers 和 org.scalatest.matchers.MustMatchers

如果你想使用更丰富的更个性的断言表达式,可以在你的单元测试类里面混入这两个匹配器

他们的表达方式是这样的:

 

Java代码   收藏代码
  1. object should equal (3) 和 object must equal (3)  
 

他们还有很多表达式这里就不一一列举了详见API 。

如果你想知道他们有什么区别,可以告诉你们这俩个类的实现方式是一样的,只是语气上是

should 和must 的区别,作用也是一样的,你比较顺眼哪个就混入哪个。

 

ScalaTest 单元测试的运行

1)org.scalatest.tools.Runner 运行

ScalaTest 的Runner 应用可以在命令行或ant 任务中调用。前提条件是被测试对象必须是Suite 测试集。Runner 工具运行必须指定要运行的测试集,方式包括显式说明测试集名称或者说明你想要Runner 执行自动发现的测试集名称前缀。你可以选择性地指定运行路径:runpath ,目录列表和装载测试类的JAR 文件以及它们测试的代码。你还可以指定一个或多个报表器,以格式化测试结果的外观。例如,ScalaTest 的发布包里包含了测试ScalaTest 自身的测试集。你可以使用下列命令执行其中的测试集,SuiteSuite :

        我在本机进入scalatest-1.2 的安装目录下,输入

        >scala – cp scalatest-1.2.jar org.scalatest.tools.Runner

              -p "scalatest-1.2-tests.jar" – s org.scalatest.SuiteSuite

        就可以运行SuiteSuite 这个测试集了,还会有工具自带的GUI 窗口显示:


ScalaTest_第1张图片

 

 

-cp 的目的是把 ScalaTest 的 JAR 文件放在类路径中。下一项,org.scalatest.tools.Runner ,是 Runner 应用的全称。Scala 将运行这个应用并把剩余的项当做命令行参数传递给应用。-p 指定了运行路径,这里是包含了测试集类的 JAR 文件:scalatest-1.2-tests.jar 。-s 说明了SuiteSuite 是要执行的测试集。

如果每一个Suite 测试集都要输一个命令行来执行的话,必然是相当麻烦,下面就来看看在ant 任务中配置Runner运行脚本是怎么样的:

最主要的就是配置ant 的build.xml ,写好这个配置文件,Eclipse 想要运行build 任务,就只需调用ant 工具就可以了。这个是build.xml 的主要配置代码:引入了scalatest 提供的

org.scalatest.tools.ScalaTestAntTask 标签库。        

 

Xml代码   收藏代码
  1. xml version="1.0" encoding="GB2312"?>  
  2. <project name="scala_ceshi" default="test" basedir=".">  
  3. <property name="scala.home"            value="C:\Program Files\scala-2.8.0"/>     
  4. <property name="src.dir"               value="src"/>  
  5. <property name="test.dir"            value="test"/>  
  6. <property name="build.dir"             value="build"/>  
  7. <property name="build.test"         value="${build.dir}/test" />  
  8. <property name="build.classes"         value="${build.dir}/classes" />  
  9. <property name="scala-library.jar" value="${scala.home}/lib/scala-library.jar"/>  
  10. <target name="clean" description="Removes previous build">  
  11.        <delete quiet="true" verbose="false" dir="${build.dir}"/>  
  12. target>  
  13. <target name="make_dir" depends="clean">  
  14.     <mkdir dir="${build.classes}"/>  
  15.     <mkdir dir="${build.test}"/>  
  16. target>  
  17. <target name="init_classpaths" depends="make_dir">  
  18.       <path id="classpath.build">  
  19.             <pathelement location="${scala-library.jar}"/>  
  20.       path>  
  21.       <path id="classpath.test">  
  22.            <pathelement location="${build.classes}" />  
  23.             <pathelement location="C:\apache-maven-2.2.1\MyRepository\org\scalatest\scalatest\1.0.1-for-scala-2.8.0.Beta1-NQRFPT\scalatest-1.0.1-for-scala-2.8.0.Beta1-NQRFPT.jar" />  
  24.             <pathelement location="${scala-library.jar}"/>  
  25.       path>  
  26. target>  
  27. <target name="init_ant_tasks" depends="init_classpaths">  
  28.     <taskdef resource="scala/tools/ant/antlib.xml">  
  29.           <classpath>  
  30.                 <pathelement location="${scala.home}/lib/scala-compiler.jar"/>  
  31.                 <pathelement location="${scala-library.jar}"/>  
  32.           classpath>  
  33.     taskdef>  
  34.     <taskdef name="scalatest" classname="org.scalatest.tools.ScalaTestAntTask">  
  35.       <classpath refid="classpath.test"/>  
  36.     taskdef>  
  37. target>  
  38. <target name="compile" depends="init_ant_tasks">  
  39.      <scalac srcdir="${src.dir}"  
  40.             destdir="${build.classes}"  
  41.             classpathref="classpath.build"  
  42.             deprecation="on"  
  43.             force="changed">  
  44.     scalac>  
  45. target>  
  46. <target name="test" depends="compile">  
  47.     <scalac srcdir="${test.dir}"  
  48.             destdir="${build.test}"  
  49.             classpathref="classpath.test"  
  50.             force="changed">  
  51.     scalac>  
  52.     <scalatest>  
  53.         <runpath>  
  54.             <pathelement location="${build.test}"/>  
  55.         runpath>  
  56.         <reporter type="stdout"/>  
  57.         <suite classname="YourSuiteTestName"/>  
  58.     scalatest>  
  59. target>  
  60. project>  

 

 

这样就可以用 标签配置N 个Suite 测试集了。调用ant-build 既可以测试相关的单元测试。

    2 )使用JUnit 运行

    JUnit 运行scalatest 的Suite 测试集的方式也很多:

    这里就说由scalatest 自己提供的类库实现运行,

    首先是org.scalatest.junit.JUnit3Suite org.scalatest.junit.JUnitSuite

    只要你的测试集扩展了这两个类中一个类,你就可以用相应的JUnit3 或JUnit4 工具运行这个测试集,该测试集中可以使用Suite 所有断言语法,当然你的测试集也可以用scalatest 的Runner 工具运行。如果就想把测试集当成一个只用JUnit 运行的测试的话,那么你的测试集混入org.scalatest.junit.AssertionsForJunit 特质即可。

使用这种混入JUnit 特质的方式时,必须要在测试方法前加入org.junit.Test 标签,这样

JUnit 才能识别该方法的有效性。

=================================================================

接下来一种方法就是org.junit.runner.RunWith 和 org.scalatest.junit.JUnitRunner 的组合使用:

 

Java代码   收藏代码
  1. import org.junit.runner.RunWith  
  2. import org.scalatest.junit.JUnitRunner  
  3. import org.scalatest.Suite  
  4. @RunWith(classOf[JUnitRunner])  
  5. class MySuiteTest extends Suite {  
  6.     def testAddition() {  
  7.        val sum = 1 + 1  
  8.        assert(sum === 2)  
  9.        assert(sum + 2 === 4)  
  10.     }  
  11.     def testSubtraction() {  
  12.        val diff = 4 - 1  
  13.        assert(diff === 3)  
  14.        assert(diff - 2 === 1)  
  15.     }  
  16. }  
 

 

这样,JUnit 工具也可以运行这个Suite 测试集。

你可能感兴趣的:(Scala)