对一个
测试框架来说,测试结果报告是很重要的部分。但是
ruby unit
test framework并没有提供一个testrunner来输出格式化的结果,所以必须自己写一个。
RUTF的架构
在开始写自己的testrunner之前,我们需要理解ruby unit test framework(简写为RUTF)的结构。
RUTF执行TestCase的过程简单明了,它里面有4个概念
原料:TestCase/TestSuite
执行配置者:TestRunner
执行体:TestRunMediator
产品:TestResult
处在中枢位置的是TestRuner,它会创建和配置 执行体,把原料输入给执行体,并让执行体跑起来。
TestRunner和TestRunMediator的关系
需要说明一下 TestRunner和TestRunMediator的关系。这是一个 监听器 模式的应用。被监听者是TestRunMediator,可以为下列事件向一个TestRunMediator注册listener。
事件的宿主 事件类型
TestRunMediator :STARTED, :FINISHED, :RESET
TestCase :STARTED, :FINISHED
TestSuite :STARTED, :FINISHED
TestResult :FAULT, :CHANGED
而TestRunner正是通过提供不同的listener,而获得不同形式的结果报告。所以为了获得格式化的测试结果报告,我们需要提供自己的TestRunner。
!!!TestCase的含义,在定义时和运行时是不一样的
另外一个需要关注的地方是,对于RUTF来说,一个最小的执行单位(我叫它测试单元TestUnit,--注:这个不是RUTF的概念)不是一个 TestCase 实例,而是一个TestCase实例的一个test方法。所以在定义时有下面的事实
一个TestCase是TestUnit的集合
一个TestSuite是TestCase的集合
但在运行时,在RUTF的看来,一个test方法就是一个'testcase',而一个TestCase,作为'testcase'的集合,叫做'testsuite'。所以事件类型TestCase::STARTED表示的其实是一个test方法开始执行的事件。同理,TestSuite::STARTED表示的是我们定义的一个TestCase开始执行的事件。
转换xml形式的结果到Html
比如有下面一个testcase
# test case
class TC_Test < Test::Unit::TestCase
def test_ok
assert_equal(2, 1+1, "2=1+1")
end
def test_error
assert_true(3, 1+1, "3=1+1")
end
def test_failure
raise "failed"
end
end
# 中间结果
<suite name='TC_Test' error_count='0' failed_count='2' test_count='3' assertion_count='0' failure_count='0'>
<test name='test_error(TC_Test)' time='0.062' passed='false'>
<result error_count='1' assertion_count='0' failure_count='0'>
<fault msg='Error:
test_error(TC_Test):
ArgumentError: wrong number of arguments (3 for 2)'><![CDATA[
tc_test_2.rb:18:in `assert_true'
tc_test_2.rb:18:in `test_error'
F:\lifr\myRuby\everbright/lib/test/testrunner.rb:159:in `start_mediator'
F:\lifr\myRuby\everbright/lib/test/testrunner.rb:155:in `start'
]]></fault>
</result>
</test>
xml的结果适合作为中间数据保存,但其可视性和可理解性还不好,还需要把xml转换为html。in ruby way,最方便的是用erb模版,在加上一个css。我们就能得到漂亮的报表了。