2011-08-05 44 views
2

我在写一些ruby(不是Rails),并且用shoulda来测试/测试单元。有没有好的ruby测试追踪解决方案?

是否有任何宝石可以让我实现从测试到设计/需求的可追溯性?

即:我想与他们测试的要求,名称标记我的测试,然后生成的未测试的要求,报告或有失败的测试等

希望这不是为红宝石太enterprisey 。

谢谢!

回答

1

更新:该解决方案可作为宝石:http://rubygems.org/gems/test4requirements

是否有任何宝石是是否允许我实现从我的 测试回溯到设计/要求的可追溯性?

我不知道任何宝石,但你的需要是一个小实验的灵感,它是如何解决的。

  • 你必须与RequirementList.new(1,2,3,4)
  • 这种要求可以用要求在一个TestCase
  • 每个测试可分配分配定义您的要求在测试后要求
  • 的要求会导致你(全成)
这要求测试的概述

而现在的例子:

gem 'test-unit' 
require 'test/unit' 

########### 
# This should be a gem 
########### 

class Test::Unit::TestCase 
    def self.requirements(req) 
    @@requirements = req 
    end 
    def requirement(req) 
    raise RuntimeError, "No requirements defined for #{self}" unless defined? @@requirements 
    caller.first =~ /:\d+:in `(.*)'/ 
    @@requirements.add_test(req, "#{self.class}##{$1}") 
    end 
    alias :run_test_old :run_test 
    def run_test 
    run_test_old 
    #this code is left if a problem occured. 
    #in other words: if we reach this place, then the test was sucesfull 
    if defined? @@requirements 
     @@requirements.test_successfull("#{self.class}##{@method_name}") 
    end 
    end 
end 

class RequirementList 
    def initialize(*reqs) 
    @requirements = reqs 
    @tests = {} 
    @success = {} 

    #Yes, we need two at_exit. 
    #tests are done also at_exit. With double at_exit, we are after that. 
    #Maybe better to be added later. 
    at_exit { 
     at_exit do 
     self.overview 
     end 
    } 

    end 
    def add_test(key, loc) 
    #fixme check duplicates 
    @tests[key] = loc 
    end 
    def test_successfull(loc) 
    #fixme check duplicates 
    @success[loc] = true 
    end 
    def overview() 
    puts "Requirements overiew" 
    @requirements.each{|req| 
     if @tests[req] #test defined 
     if @success[@tests[req]] 
      puts "Requirement #{req} was tested in #{@tests[req] }" 
     else 
      puts "Requirement #{req} was unsuccessfull tested in #{@tests[req] }" 
     end 
     else 
     puts "Requirement #{req} was not tested" 
     end 
    } 
    end 
end #RequirementList 

############### 
## Here the gem end. The test will come. 
############### 

$req = RequirementList.new(1,2,3, 4) 

class MyTest < Test::Unit::TestCase 
    #Following requirements exist, and must be tested sucessfull 
    requirements $req 

    def test_1() 
    requirement(1) #this test is testing requirement 1 
    assert_equal(2,1+1) 
    end 
    def test_2() 
    requirement(2) 
    assert_equal(3,1+1) 
    end 
    def test_3() 
    #no assignment to requirement 3 
    pend 'pend' 
    end 
end 


class MyTest_4 < Test::Unit::TestCase 
    #Following requirements exist, and must be tested sucessfull 
    requirements $req 

    def test_4() 
    requirement(4) #this test is testing requirement 4 
    assert_equal(2,1+1) 
    end 
end 

结果:

Loaded suite testing_traceability_solutions 
Started 
.FP. 

    1) Failure: 
test_2(MyTest) 
    [testing_traceability_solutions.rb:89:in `test_2' 
    testing_traceability_solutions.rb:24:in `run_test']: 
<3> expected but was 
<2>. 

    2) Pending: pend 
test_3(MyTest) 
testing_traceability_solutions.rb:92:in `test_3' 
testing_traceability_solutions.rb:24:in `run_test' 

Finished in 0.65625 seconds. 

4 tests, 3 assertions, 1 failures, 0 errors, 1 pendings, 0 omissions, 0 notifications 
50% passed 
Requirements overview: 
Requirement 1 was tested in MyTest#test_1 
Requirement 2 was unsuccessfull tested in MyTest#test_2 
Requirement 3 was not tested 
Requirement 4 was tested in MyTest_4#test_4 

如果你认为,这可能是一个解决方案给你,请给我一个反馈。然后我会尝试从它身上创建一个宝石。


代码示例使用与早该

#~ require 'test4requirements' ###does not exist/use code above 
require 'shoulda' 
#use another interface ##not implemented### 
#~ $req = Requirement.new_from_file('requirments.txt') 

class MyTest_shoulda < Test::Unit::TestCase 
    #Following requirements exist, and must be tested sucessfull 
    #~ requirements $req 

    context 'req. of customer X' do 
    #Add requirement as parameter of should 
    # does not work yet 
    should 'fullfill request 1', requirement: 1 do 
     assert_equal(2,1+1) 
    end 
    #add requirement via requirement command 
    #works already 
    should 'fullfill request 1' do 
     requirement(1) #this test is testing requirement 1 
     assert_equal(2,1+1) 
    end 
    end #context 
end #MyTest_shoulda 
+0

这看起来像个好主意 - 我正在考虑以不同的方式滚动自己。我的reqs在一个txt文件中,每个文件都有一个标签[REQnnnn]。然后,我将这个标签添加到每个测试中的“应该”行(我正在使用shoulda)。我最后一步是编写一个运行单元测试的TestRunner类,抓取输出并对照需求txt文件进行交叉检查。感谢您的灵感。 –

+0

我刚刚添加了与shoulda一起使用的代码示例。你觉得那样吗? Requirement#new_by_file将读取一个包含需求的文本文件。你有特殊的格式吗?我会推荐一个yaml文件。 – knut

+0

此代码作为宝石的预发布版本可在http://rubygems.org/gems/test4requirements – knut

1

随着cucumber你可以有你的要求是测试,没有得到任何比这更可追踪:)

所以一个要求是功能,和功能有要测试场景。

# addition.feature 

Feature: Addition 
    In order to avoid silly mistakes 
    As a math idiot 
    I want to be told the sum of two numbers 

    Scenario Outline: Add two numbers 
    Given I have entered <input_1> into the calculator 
    And I have entered <input_2> into the calculator 
    When I press <button> 
    Then the result should be <output> on the screen 

    Examples: 
    | input_1 | input_2 | button | output | 
    | 20  | 30  | add | 50  | 
    | 2  | 5  | add | 7  | 
    | 0  | 40  | add | 40  | 

那么你已经使用Ruby编写的步骤定义映射到场景

# step_definitons/calculator_steps.rb 

begin require 'rspec/expectations'; rescue LoadError; require 'spec/expectations'; end 
require 'cucumber/formatter/unicode' 
$:.unshift(File.dirname(__FILE__) + '/../../lib') 
require 'calculator' 

Before do 
    @calc = Calculator.new 
end 

After do 
end 

Given /I have entered (\d+) into the calculator/ do |n| 
    @calc.push n.to_i 
end 

When /I press (\w+)/ do |op| 
    @result = @calc.send op 
end 

Then /the result should be (.*) on the screen/ do |result| 
    @result.should == result.to_f 
end 
+0

这看起来很漂亮,但我不知道它会为我工作。例如,我的一个测试检查一个方法的返回值,该方法是一个包含150个元素的3D数组。我如何在黄瓜中做到这一点? (我已经写在测试/单元中。) –