test4requirements 0.1.0.alpha.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,5 @@
1
1
  =begin rdoc
2
2
  Define a requirement.
3
-
4
3
  =end
5
4
  module Test4requirements
6
5
  class Requirement
@@ -8,19 +7,24 @@ module Test4requirements
8
7
  OPTIONS = [
9
8
  :description,
10
9
  :reference,
10
+ :key, #optional, but must be identic with first parameter
11
11
  ]
12
12
  =begin rdoc
13
13
  Each requirement must include a key.
14
14
 
15
15
  Optional values:
16
16
  * description
17
- * reference
17
+ * reference, e.g. 'Customer Requirement, Version 2011-08-02, page 12'
18
+
18
19
  =end
19
20
  def initialize( key, options = {} )
21
+
20
22
  @key = key
21
23
  options.keys.each{|key|
22
- raise ArgumentError, "Key #{key} undefined" unless OPTIONS.include?(key)
24
+ raise ArgumentError, "#{self.class}.new: Option #{key} undefined" unless OPTIONS.include?(key)
23
25
  }
26
+ raise ArgumentError, "#{self.class}.new: Key not explicit: #{key}" if options[:key] and options[:key] != key
27
+
24
28
  @description = options[:description]
25
29
  @reference = options[:reference]
26
30
 
@@ -36,8 +40,16 @@ Optional values:
36
40
  attr_reader :reference
37
41
  #Logger. Defined by RequirementList#<<
38
42
  attr_accessor :log
43
+ #Testcases of the requirement
44
+ attr_reader :tests
39
45
 
40
-
46
+ =begin rdoc
47
+ Assign a TestCase.
48
+ =end
49
+ def test=(loc)
50
+ @log.info("Test #{loc} assigned to requirement #{@key}") if @log and @log.info?
51
+ @tests[loc] = [] #Collects problems
52
+ end
41
53
  =begin rdoc
42
54
  Returns the result of a TestCase.
43
55
 
@@ -46,46 +58,38 @@ Returns the result of a TestCase.
46
58
  * true: Succesfull tested
47
59
  =end
48
60
  def [](key)
49
- @tests[key]
61
+ return nil unless @tests[key]
62
+ return @tests[key].uniq == [:ok]
50
63
  end
51
-
52
64
  =begin rdoc
53
- Assign a TestCase.
65
+ Set a result for a test case.
54
66
  =end
55
- def test=(loc)
56
- @log.info("Test #{loc} assigned to requirement #{@key}") if @log and @log.info?
57
- @tests[loc] = false #Will be tested
58
- end
59
-
60
- =begin rdoc
61
- Mark a test as successfull.
62
- =end
63
- def successfull_test(loc)
64
- #fixme: Check if already defined?
65
- #~ raise ArgumentError, "Successfull test #{loc} was never assigned" unless @tests.has_key?(loc)
66
- @log.info("Test #{loc} successfull for to requirement #{@key}") if @log and @log.info?
67
- @tests[loc] = true #Was successfull tested
67
+ def result(key, val)
68
+ @tests[key] ||= []
69
+ @tests[key] << val
68
70
  end
71
+
69
72
  =begin rdoc
70
73
  Return false, if no test is defined.
71
74
  Else you get the number of tests.
72
75
  =end
73
- def tested?()
76
+ def test_defined?()
74
77
  return @tests.empty? ? false : @tests.size
75
78
  end
76
79
  =begin rdoc
77
80
  Test, if the requirement was successfull.
78
81
 
79
82
  If there is one test without success, the requirement is not successfull solved.
80
- * nil: no test found
83
+ * nil: no test found or one test not executed
81
84
  * false: At least one test not successfull
82
85
  * true: Succesfull tested
83
86
  =end
84
87
  def successfull?()
85
- return nil if @tests.empty?
88
+ return nil unless test_defined?
86
89
  success = true
87
90
  @tests.each{|key,result|
88
- success = (success and result)
91
+ return nil if result.empty?
92
+ success = (success and (result - [:ok]).empty?)
89
93
  }
90
94
  return success
91
95
  end
@@ -96,7 +100,10 @@ Return a list of tests with test result.
96
100
  #single tests: Only key returned
97
101
  #~ return @tests.keys if @tests.size == 1
98
102
  res_ok = []
99
- res_err = []
103
+ res_fail = []
104
+ res_pend = []
105
+ res_omit = []
106
+ res_error = [] #enclear erros status
100
107
  @tests.each{|key, result|
101
108
  #Convert key (for shoulda)
102
109
  case key
@@ -106,20 +113,27 @@ Return a list of tests with test result.
106
113
  key = "#{$2} (#{$1}/#{$3})"
107
114
  end
108
115
 
109
- if result
116
+ if result.include?(:failure)
117
+ res_fail << key
118
+ elsif result.include?(:pend)
119
+ res_pend << key
120
+ elsif result.include?(:omit)
121
+ res_omit << key
122
+ elsif result.include?(:ok)
110
123
  res_ok << key
111
124
  else
112
- res_err << key
125
+ res_error << key
113
126
  end
127
+
114
128
  }
115
- #return filled array, if other array is empty
116
- return res_ok if res_err.empty?
117
- return res_err if res_ok.empty?
118
129
 
119
- [
120
- "OK: #{res_ok.join(', ')}",
121
- "Failure: #{res_err.join(', ')}",
122
- ]
130
+ res = []
131
+ res << "OK: #{res_ok.join(', ')}" unless res_ok.empty?
132
+ res << "Failure: #{res_fail.join(', ')}" unless res_fail.empty?
133
+ res << "Pending: #{res_pend.join(', ')}" unless res_pend.empty?
134
+ res << "Omission: #{res_omit.join(', ')}" unless res_omit.empty?
135
+ res << "Error: #{res_omit.join(', ')}" unless res_error.empty?
136
+ res
123
137
  end
124
138
 
125
139
  def to_s()
@@ -129,4 +143,11 @@ Return a list of tests with test result.
129
143
  #~ "<Requirement #{key} #{@tests}>"
130
144
  #~ end
131
145
  end
132
- end #module Test4requirements
146
+ end #module Test4requirements
147
+
148
+ __END__
149
+ req = Test4requirements::Requirement.new(1)
150
+ req.test='loc'
151
+ req.result('loc',:ok)
152
+ p req.test_defined?
153
+ p req.successfull?
@@ -15,14 +15,42 @@ This class can be used in Test::Unit::TestCase#assign_requirement.
15
15
  =begin rdoc
16
16
  Define a list of requirements.
17
17
 
18
- Parameters will define the key of new Requirement, unless it is no Requirement.
18
+ Parameters:
19
+ * name
20
+ * list of requirement (keys)
21
+ * options
22
+ * :requirements
23
+ * :log Define a logger
24
+
25
+ The list of requirements will define the key of a new Test4requirements::Requirement,
26
+ unless it is already a Test4requirements::Requirement.
27
+
28
+ Examples:
29
+ RequirementList.new('Request_4711')
30
+ RequirementList.new('Request_4711', :req1, :req2 )
31
+ RequirementList.new('Request_4711', Reqirement.new(:req1), Reqirement.new(:req2) )
32
+ RequirementList.new('Request_4711',
33
+ :requirements => [ :req1, :req2]
34
+ )
35
+ RequirementList.new('Request_4711',
36
+ Reqirement.new(:req1), Reqirement.new(:req2),
37
+ :requirements => [ :req3, :req4]
38
+ )
39
+
19
40
  =end
20
- def initialize( *reqs )
41
+ def initialize( name, *args )
21
42
 
22
- @log = Log4r::Logger.new('ReqL')
43
+ options = {
44
+ :log => Log4r::Logger.new('ReqL'),
45
+ :requirements => [],
46
+ }.merge( args.last.is_a?(Hash) ? args.pop : {} )
47
+ options[:requirements].concat(args)
48
+
49
+ @name = name
50
+ @log = options[:log]
23
51
 
24
52
  @requirements = {}
25
- reqs.each{|req|
53
+ options[:requirements].each{|req|
26
54
 
27
55
  #Define a requirement.
28
56
  if ! req.is_a?(Requirement)
@@ -31,7 +59,8 @@ Parameters will define the key of new Requirement, unless it is no Requirement.
31
59
 
32
60
  self << req
33
61
  }
34
-
62
+ @testsresults = []
63
+
35
64
  #Yes, we need two at_exit.
36
65
  #tests are done also at_exit. With double at_exit, we are after that.
37
66
  #Maybe better to be added later.
@@ -42,8 +71,13 @@ Parameters will define the key of new Requirement, unless it is no Requirement.
42
71
  }
43
72
  @report_type = self.class.report_type_default # alternatives: nil, :stdout, :txt
44
73
  end #initialize
74
+ #Name or ID of the requirement list.
75
+ attr_reader :name
45
76
  #Logger
46
77
  attr_reader :log
78
+ #List of related result objects Test::Unit::TestResult (one per suite, normally only 1)
79
+ attr_reader :testsresults
80
+
47
81
  =begin rdoc
48
82
  Add a new requirement.
49
83
  =end
@@ -57,32 +91,67 @@ Add a new requirement.
57
91
  @requirements[req.key] = req
58
92
  end
59
93
  =begin rdoc
94
+ Method to load requirements.
95
+
96
+ You can provide:
97
+ * an array of hashes with requirement definition
98
+ * a hash with key and requirement definition
99
+
100
+ The requirement definition can contain the options of Test4requirements::Requirement.
101
+
102
+ You may use yaml to define your requirments:
103
+ req = RequirementList.new('Requirementlist')
104
+ req.load( YAML.load( <<yaml
105
+ req1:
106
+ description: 'What is required',
107
+ reference: 'Customer Requirement, Version 2011-08-02, page 12'
108
+ req2:
109
+ description: 'What is required',
110
+ reference: 'Customer Requirement, Version 2011-08-02, page 13'
111
+ yaml
112
+ ))
113
+ =end
114
+ def load( data )
115
+
116
+ if data.is_a?(Hash)
117
+ #build array
118
+ datalist = []
119
+ data.each{|key,value| datalist << value.merge(:key => key )}
120
+ else
121
+ datalist = data
122
+ end
123
+ datalist.each{|req|
124
+ self << Requirement.new( req[:key], req )
125
+ }
126
+ end
127
+ =begin rdoc
60
128
  Returns Requirement
61
129
  =end
62
130
  def [](key)
63
131
  @requirements[key]
64
132
  end
65
133
  =begin rdoc
134
+ Loop on all requirements.
135
+
136
+ Returns list of all requirements.
137
+ =end
138
+ def each()
139
+ @requirements.each{|key,req| yield req} if block_given?
140
+ @requirements.values
141
+ end
142
+ =begin rdoc
66
143
  Assign a testcase to an requirement.
67
144
 
68
145
  Requires:
69
146
  * Requirement key
70
147
  * testcase (Class#methodname)
71
148
  =end
72
- def assign_test(req, testcase)
149
+ def assign_test(req, testcase, result)
73
150
  raise ArgumentError unless @requirements[req]
151
+ #~ raise ArgumentError, "result is no Test::Unit::TestResult but #{result.inspect}" unless result.is_a?(Test::Unit::TestResult)
74
152
  @requirements[req].test= testcase
75
- end
76
- =begin rdoc
77
- Report successfull test to the requirement.
78
-
79
- This requires a previous assignment with #assign_test.
80
- =end
81
- def test_successfull(loc)
82
- #~ raise ArgumentError unless @requirements[req]
83
- @requirements.each{|key,req|
84
- req.successfull_test(loc) unless req[loc].nil?
85
- }
153
+ #Assign the related result object Test::Unit::TestResult
154
+ @testsresults << result unless @testsresults.include?(result)
86
155
  end
87
156
  =begin rdoc
88
157
  Defines, how and if an overview of the requirements are given.
@@ -99,6 +168,28 @@ Used in #overview. More details see there.
99
168
  end
100
169
  end
101
170
  =begin rdoc
171
+ =end
172
+ def analyse_testresults()
173
+ @testsresults.each{|result|
174
+ result.faults.each{|fault|
175
+ self.each{|req|
176
+ if ! req[fault.test_name].nil?
177
+ @log.debug("Set result #{fault} to #{req}") if @log.info?
178
+ case fault
179
+ when Test::Unit::Failure; req.result(fault.test_name, :failure)
180
+ when Test::Unit::Pending; req.result(fault.test_name, :pend)
181
+ when Test::Unit::Omission; req.result(fault.test_name, :omit)
182
+ else
183
+ @log.error("unknown fault-type #{fault.inspect}") if @log.error?
184
+ req.set_result(fault.test_name, :error)
185
+ end
186
+ end
187
+ }
188
+
189
+ }
190
+ }
191
+ end
192
+ =begin rdoc
102
193
  Give an overview.
103
194
 
104
195
  Returns a hash with test results for the requirements.
@@ -113,6 +204,8 @@ The parameter defines alternative report types:
113
204
  =end
114
205
  def overview(report_type = @report_type )
115
206
 
207
+ analyse_testresults()
208
+
116
209
  txt = []
117
210
  hash = {}
118
211
 
@@ -120,7 +213,7 @@ The parameter defines alternative report types:
120
213
  if req.successfull?
121
214
  txt << "Requirement #{key} was successfull tested (#{req.testresults.join(', ')})"
122
215
  hash[key] = true
123
- elsif req.tested?
216
+ elsif req.test_defined?
124
217
  txt << "Requirement #{key} was unsuccessfull tested (#{req.testresults.join(', ')})"
125
218
  hash[key] = false
126
219
  else
@@ -1,77 +1,114 @@
1
- =begin rdoc
2
- Support of shoulda.
3
-
4
- Details on usage see examples/example_test4requirements_shoulda.rb
5
-
6
- Fixmes:
7
- * should_not is not supported yet
8
- =end
9
-
10
- require_relative '../test4requirements'
11
- require 'shoulda' #tested with shoulda 2.11.3
12
-
13
- #
14
- module Test
15
- module Unit
16
- class TestCase
17
- class << self
18
- #remember original definition.
19
- alias :should_old :should
20
- =begin rdoc
21
- Extend #should to support assignment to requirement.
22
-
23
- Usage:
24
- should 'fullfill request 1', requirement: :req1 do
25
- assert_equal(2,1+1)
26
- end
27
- =end
28
- def should(name_or_matcher, options = {}, &blk)
29
- if ! self.name
30
- raise RuntimeError, "Shoulda not defined for anonymous classes"
31
- end
32
- if options[:requirement]
33
- #testmethodname must fit self.name of the later test (TestCase#run_test)
34
- testmethodname = 'test: '
35
- testmethodname << self.name.gsub(/Test/, "")
36
- testmethodname << ' should '
37
- testmethodname << name_or_matcher
38
- testmethodname << '. '
39
- testmethodname << "(#{self.name})"
40
- raise RuntimeError, "No requirements defined for #{self}" unless get_requirements
41
- get_requirements.assign_test(options[:requirement], testmethodname)
42
- end
43
- should_old(name_or_matcher, options = {}, &blk)
44
- end #should
45
- end #eigenclass TestCase
46
- end #class TestCase
47
- end #module Unit
48
- end #module Test
49
-
50
- module Shoulda
51
- class Context
52
- #remember original definition.
53
- alias :should_old :should
54
- =begin rdoc
55
- Extend #should inside a context to support assignment to requirement.
56
-
57
- Usage:
58
- should 'fullfill request 1', requirement: :req1 do
59
- assert_equal(2,1+1)
60
- end
61
- =end
62
- def should(name_or_matcher, options = {}, &blk)
63
- if options[:requirement]
64
- #testmethodname must fit self.name of the later test (TestCase#run_test)
65
- testmethodname = 'test: '
66
- testmethodname << self.name
67
- testmethodname << ' should '
68
- testmethodname << name_or_matcher
69
- testmethodname << '. '
70
- testmethodname << "(#{self.parent.name})"
71
- raise RuntimeError, "No requirements defined for #{self}" unless get_requirements
72
- get_requirements.assign_test(options[:requirement], testmethodname)
73
- end
74
- should_old(name_or_matcher, options = {}, &blk)
75
- end #should
76
- end# class Context
77
- end #Shoulda
1
+ =begin rdoc
2
+ Support of shoulda.
3
+
4
+ Details on usage see examples/example_test4requirements_shoulda.rb
5
+
6
+ Fixmes:
7
+ * should_not is not supported yet
8
+ =end
9
+
10
+ require_relative '../test4requirements'
11
+ require 'shoulda' #tested with shoulda 2.11.3
12
+
13
+ #
14
+ module Test4requirements
15
+ =begin rdoc
16
+ Dummy class TestResults for use with Shoulda
17
+ =end
18
+ class TestResults
19
+ def initialize()
20
+ @faults = []
21
+ end
22
+ attr_reader :faults
23
+ end #class TestResults
24
+ end #module Test4requirements
25
+
26
+ module Test
27
+ module Unit
28
+ class TestCase
29
+ class << self
30
+ #remember original definition.
31
+ alias :should_old :should
32
+ =begin rdoc
33
+ Extend #should to support assignment to requirement.
34
+
35
+ Usage:
36
+ should 'fullfill request 1', requirement: :req1 do
37
+ assert_equal(2,1+1)
38
+ end
39
+ =end
40
+ def should(name_or_matcher, options = {}, &blk)
41
+ if ! self.name
42
+ raise RuntimeError, "Shoulda not defined for anonymous classes"
43
+ end
44
+ if options[:requirement]
45
+ #testmethodname must fit self.name of the later test (TestCase#run_test)
46
+ testmethodname = 'test: '
47
+ testmethodname << self.name.gsub(/Test/, "")
48
+ testmethodname << ' should '
49
+ testmethodname << name_or_matcher
50
+ testmethodname << '. '
51
+ testmethodname << "(#{self.name})"
52
+ raise RuntimeError, "No requirements defined for #{self}" unless get_requirements
53
+ get_requirements.assign_test(options[:requirement], testmethodname, Test4requirements::TestResults.new)
54
+ end
55
+ should_old(name_or_matcher, options = {}, &blk)
56
+ end #should
57
+ end #eigenclass TestCase
58
+ end #class TestCase
59
+ end #module Unit
60
+ end #module Test
61
+
62
+ module Shoulda
63
+ class Context
64
+ #remember original definition.
65
+ alias :should_old :should
66
+ =begin rdoc
67
+ Extend #should inside a context to support assignment to requirement.
68
+
69
+ Usage:
70
+ should 'fullfill request 1', requirement: :req1 do
71
+ assert_equal(2,1+1)
72
+ end
73
+ =end
74
+ def should(name_or_matcher, options = {}, &blk)
75
+ if options[:requirement]
76
+ #testmethodname must fit self.name of the later test (TestCase#run_test)
77
+ testmethodname = 'test: '
78
+ testmethodname << self.name
79
+ testmethodname << ' should '
80
+ testmethodname << name_or_matcher
81
+ testmethodname << '. '
82
+ testmethodname << "(#{self.parent.name})"
83
+ raise RuntimeError, "No requirements defined for #{self}" unless get_requirements
84
+ get_requirements.assign_test(options[:requirement], testmethodname, Test4requirements::TestResults.new )
85
+ end
86
+ should_old(name_or_matcher, options = {}, &blk)
87
+ end #should
88
+ end# class Context
89
+ end #Shoulda
90
+
91
+ __END__
92
+
93
+ include Test4requirements
94
+ $reqs = RequirementList.new(:reqId, :req1,:req2,:req3)
95
+ class Testcase < Test::Unit::TestCase
96
+ #Set class name. Normally class name.
97
+ def self.name;'Test_ShouldaTest';end
98
+
99
+ self.requirements= $reqs
100
+ #Add requirement as parameter of should
101
+ should 'request_1', requirement: :req1 do
102
+ assert_equal(2,1+1)
103
+ end
104
+
105
+ #add requirement via requirement command
106
+ should 'request_2' do
107
+ assign_requirement(:req2) #this test is testing requirement 1
108
+ assert_equal(3,1+1)
109
+ end
110
+ end
111
+
112
+ #~ suite = @testcase.suite #run tests
113
+ #~ Test::Unit::UI::Console::TestRunner.run(suite, :output => IO_Catcher)
114
+ p $reqs.overview