rcor 0.8.1 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/Rakefile.rb +1 -1
  2. data/lib/concordion.rb +1 -8
  3. data/lib/concordion_constants.rb +1 -1
  4. data/lib/concordion_css.rb +8 -1
  5. data/lib/concordion_css_decorator.rb +21 -4
  6. data/lib/concordion_error_condition.rb +26 -0
  7. data/lib/concordion_invoker.rb +103 -9
  8. data/lib/concordion_parse_result.rb +19 -1
  9. data/lib/concordion_parser.rb +1 -1
  10. data/lib/concordion_processor.rb +3 -2
  11. data/lib/concordion_string_utility.rb +36 -2
  12. data/lib/concordion_test_case.rb +12 -62
  13. data/lib/concordion_test_methods.rb +127 -0
  14. data/lib/concordion_utility.rb +15 -3
  15. data/lib/goldmaster_test_case.rb +22 -5
  16. data/lib/loader_helper.rb +16 -0
  17. data/nbproject/private/private.xml +0 -6
  18. data/nbproject/private/rake-d.txt +13 -0
  19. data/tests/apostrophe.html +7 -0
  20. data/tests/apostrophe_test.rb +18 -0
  21. data/tests/ariel_example.html +13 -0
  22. data/tests/ariel_example_test.rb +36 -0
  23. data/tests/attr_assert.html +2 -0
  24. data/tests/basic_assert_true_test.rb +5 -1
  25. data/tests/basic_set.html +3 -0
  26. data/tests/basic_text.html +8 -0
  27. data/tests/basic_text_test.rb +11 -0
  28. data/tests/concordion_parse_result_test.rb +16 -1
  29. data/tests/concordion_test.rb +0 -14
  30. data/tests/concordion_utility_test.rb +44 -0
  31. data/tests/failing.html +4 -0
  32. data/tests/failing_test.rb +10 -2
  33. data/tests/goldmaster_assert_true_failing.html +5 -0
  34. data/tests/goldmaster_assert_true_failing_goldmaster.html +169 -0
  35. data/tests/goldmaster_assert_true_failing_test.rb +14 -0
  36. data/tests/goldmaster_failing.html +40 -0
  37. data/tests/goldmaster_failing_goldmaster.html +48 -1
  38. data/tests/goldmaster_failing_test.rb +28 -2
  39. data/tests/goldmaster_malformed.html +7 -0
  40. data/tests/goldmaster_malformed_goldmaster.html +171 -0
  41. data/tests/goldmaster_malformed_test.rb +11 -0
  42. data/tests/goldmaster_passing_goldmaster.html +8 -1
  43. data/tests/goldmaster_table_bug.html +12 -0
  44. data/tests/goldmaster_table_bug_goldmaster.html +176 -0
  45. data/tests/goldmaster_table_bug_test.rb +24 -0
  46. data/tests/goldmaster_table_goldmaster.html +8 -1
  47. data/tests/image.html +5 -0
  48. data/tests/image.jpg +0 -0
  49. data/tests/image_test.rb +9 -0
  50. data/tests/mixed.html +5 -0
  51. data/tests/mixed_test.rb +19 -0
  52. data/tests/no_parens.html +15 -0
  53. data/tests/no_parens_test.rb +20 -0
  54. data/tests/numbers.html +5 -0
  55. data/tests/numbers_test.rb +11 -0
  56. data/tests/verify_rows_scsr_test.rb +2 -0
  57. data/tests/verify_rows_simple.html +14 -0
  58. data/tests/verify_rows_simple_test.rb +17 -0
  59. metadata +31 -4
  60. data/lib/concordion_invocation_string_builder.rb +0 -24
@@ -17,7 +17,7 @@ end
17
17
  task :default => [:clean, :test]
18
18
 
19
19
  PKG_FILES = FileList['**/*'].exclude(/_test_output\.html$/)
20
- PKG_VERSION = '0.8.1'
20
+ PKG_VERSION = '0.9.5'
21
21
 
22
22
  spec = Gem::Specification.new do |s|
23
23
  s.platform = Gem::Platform::RUBY
@@ -1,5 +1,4 @@
1
1
  require 'concordion_utility'
2
- require 'concordion_invocation_string_builder'
3
2
  require 'concordion_lookahead_handler'
4
3
  require 'concordion_verifier'
5
4
  require 'concordion_invoker'
@@ -12,11 +11,10 @@ class Concordion
12
11
  def self.TEXT_VAR
13
12
  @@TEXT_VAR
14
13
  end
15
- attr_reader :verification_variable, :verifier, :invocation_builder
14
+ attr_reader :verification_variable, :verifier
16
15
 
17
16
  def initialize
18
17
  @memory = {}
19
- @invocation_builder = ConcordionInvocationStringBuilder.new(self)
20
18
  @lookahead_handler = ConcordionLookaheadHandler.new
21
19
  @verifier = ConcordionVerifier.new(self)
22
20
  @invoker = ConcordionInvoker.new(self)
@@ -31,9 +29,6 @@ class Concordion
31
29
  @memory[variable]
32
30
  end
33
31
 
34
- def build_invocation_string(conc_call, content)
35
- @invocation_builder.build_invocation_string(conc_call,content)
36
- end
37
32
 
38
33
  def dereference(conc_call)
39
34
  var_name = concordion_variable_name(conc_call)
@@ -61,6 +56,4 @@ class Concordion
61
56
  conc_rv
62
57
  end
63
58
 
64
-
65
-
66
59
  end
@@ -1,7 +1,7 @@
1
1
  module ConcordionConstants
2
2
 
3
3
  def concordion_command_attributes
4
- ["assertequals", "set", "execute", "verifyrows", "asserttrue"].collect do
4
+ ["assertequals", "set", "execute", "verifyrows", "asserttrue", "assert_image"].collect do
5
5
  |cmd| "concordion:#{cmd}"
6
6
  end
7
7
  end
@@ -68,7 +68,7 @@ p.success {
68
68
  padding: 2px;
69
69
  }
70
70
  .concordion_success, .concordion_success * {
71
- background-color: #afa !important;
71
+ background-color: #afa;
72
72
  }
73
73
  .success pre {
74
74
  background-color: #bbffbb;
@@ -82,6 +82,13 @@ p.success {
82
82
  color: #bb5050;
83
83
  }
84
84
 
85
+ td.concordion_failure {
86
+ background-color: #ffb0b0 !important;
87
+ }
88
+ td.concordion_success {
89
+ background-color: #afa !important;
90
+ }
91
+
85
92
  ins {
86
93
  text-decoration: none;
87
94
  }
@@ -1,4 +1,5 @@
1
1
  require 'concordion_css'
2
+ require 'concordion_error_condition'
2
3
 
3
4
  class ConcordionCSSDecorator
4
5
  def add_concordion_css_link(root, html, type)
@@ -39,14 +40,30 @@ class ConcordionCSSDecorator
39
40
  end
40
41
  end
41
42
 
42
- def decorate_tag(rv, tag)
43
+ def decorate_tag(rv, tag, cpr)
44
+ context = tag.to_html
45
+ expected = tag.inner_html
46
+ xpath = tag.xpath
47
+
43
48
  if rv[:result]
44
49
  tag[:class] = 'concordion_success'
45
- return 0
50
+ return nil
46
51
  end
47
52
 
48
53
  tag[:class] = 'concordion_failure'
49
- tag.inner_html += " expected but received #{rv[:actual]}"
50
- 1
54
+ if cpr.is_verify_command?
55
+ if rv[:actual] > rv[:expected]
56
+ diff = rv[:actual] - rv[:expected]
57
+ tag.inner_html += "<tr><td>[#{diff} Surplus Row(s) Returned By Fixture]</td></tr>"
58
+ end
59
+ else
60
+ if cpr.is_assert_true_command?
61
+ tag.inner_html += ": expected true but received #{rv[:actual]}"
62
+ else
63
+ tag.inner_html += " expected but received #{rv[:actual]}"
64
+ end
65
+ end
66
+ #TODO refactor: move some of this logic into the conc parse result?
67
+ ConcordionErrorCondition.new(expected, rv[:actual], xpath, context, cpr.is_assert_true_command?)
51
68
  end
52
69
  end
@@ -0,0 +1,26 @@
1
+ #
2
+ # To change this template, choose Tools | Templates
3
+ # and open the template in the editor.
4
+
5
+
6
+ class ConcordionErrorCondition
7
+ attr_reader :expected, :actual
8
+ def initialize(expected, actual, xpath, context = nil, assert_true_command = false)
9
+ @expected = expected
10
+ @actual = actual
11
+ @xpath = xpath
12
+ @context = context
13
+ @assert_true_command = assert_true_command
14
+ end
15
+
16
+ def to_s
17
+ @expected = "true" if @assert_true_command
18
+
19
+ base = "expected (#{@expected}) but got (#{@actual}) in tag: #{@xpath}"
20
+
21
+
22
+ return base if @context.nil?
23
+
24
+ base + "\n\tcontext of error: #{@context}"
25
+ end
26
+ end
@@ -1,31 +1,125 @@
1
+ require 'loader_helper'
2
+ require 'concordion_utility'
3
+
1
4
  class ConcordionInvoker
5
+ include LoaderHelper
6
+ include ConcordionUtility
7
+
2
8
  def initialize(conc)
3
9
  @concordion = conc
4
- @builder = conc.invocation_builder
5
10
  end
6
11
 
12
+ def try_to_dereference(cpr)
13
+ rv = nil
14
+ begin
15
+ rv = @concordion.dereference(cpr.system_under_test)
16
+ rescue NoMethodError => e
17
+ method = method_from_no_method_error(e)
18
+
19
+ rv = dereference_error_message(e)
20
+ end
21
+ rv
22
+ end
23
+
24
+ def dereference_error_message(e)
25
+ rv = "["
26
+ clazz = e.to_s.split(":")[1]
27
+ if clazz == 'NilClass'
28
+ rv += "No more rows"
29
+ else
30
+ rv += " on #{clazz} but was not found"
31
+ end
32
+ rv += "]"
33
+ end
34
+
35
+
7
36
  def invoke_sut(cpr, test_context)
8
37
  sut_rv = nil
9
38
  if cpr.needs_dereference?
10
- sut_rv = @concordion.dereference(cpr.system_under_test)
39
+ sut_rv = try_to_dereference(cpr)
11
40
  else
12
- invocation_str = @builder.build_invocation_string(cpr.system_under_test, cpr.content)
13
- sut_rv = test_context.instance_eval invocation_str
41
+
42
+ sut_rv = try_to_invoke_sut(cpr,test_context)
14
43
  end
15
44
 
16
45
  sut_rv
17
46
  end
47
+
48
+
49
+ def try_to_invoke_sut(cpr, test_context)
50
+ sut_rv = nil
51
+ begin
52
+ #TODO refactor, inlined/amended from former string builder
53
+ conc_method = concordion_method_name(cpr.system_under_test)
54
+ arg_values = []
55
+ if has_arguments?(cpr.system_under_test)
56
+ arg_vars = concordion_arguments(cpr.system_under_test)
57
+ arg_values = arg_vars.collect {|var|
58
+ if var == '#TEXT'
59
+ escape_single_quotes(cpr.content)
60
+ else
61
+ @concordion.get_variable(var)
62
+ end
63
+ }
64
+ end
65
+ args = arg_values.join(",")
66
+ sut_rv = test_context.send(conc_method, *arg_values)
67
+ rescue NoMethodError => e
68
+
69
+ if e.to_s =~ /nil:NilClass/
70
+ sut_rv = "[Parse failed for: #{cpr}, cause: (#{e})]"
71
+ else
72
+ method = method_from_no_method_error(e)
73
+ clazz = class_from_no_method_error(e)
74
+ sut_rv = "[Missing method '#{method}' in fixture #{clazz} ]"
75
+ end
76
+ end
77
+ sut_rv
78
+ end
79
+
80
+ def method_from_no_method_error(e)
81
+ except_str_from(e).split("`")[1].split("'")[0]
82
+ end
83
+
84
+ def except_str_from(e)
85
+ e.exception.to_s
86
+ end
87
+
88
+ def class_from_no_method_error(e)
89
+ except_str_from(e).split("<")[1].split(":")[0]
90
+ end
91
+
18
92
  def invoke_concordion(cpr, sut_rv)
19
- commands[cpr.concordion_command].call(sut_rv, cpr.content)
93
+ cmd = commands[cpr.concordion_command]
94
+ if cpr.is_assert_image_command?
95
+ cmd.call(sut_rv, cpr.image_location)
96
+ elsif cpr.is_verify_command?
97
+ cmd.call(sut_rv, cpr.num_results_expected)
98
+ else
99
+ cmd.call(sut_rv, cpr.content)
100
+ end
101
+
20
102
  end
21
103
 
22
104
 
23
105
  def commands
24
106
  cmds = {}
25
- cmds["assertequals"] = Proc.new { |a, b| { :result => a == b, :actual => a, :expected => b } }
26
- cmds["execute"] = Proc.new { |a,b| {:result => true, :actual => a, :expected => b } }
27
- cmds["verifyrows"] = Proc.new { |a,b| { :result => true, :actual => a, :expected => b } }
28
- cmds["asserttrue"] = Proc.new { |a, b| { :result => a, :actual => a, :expected => true } }
107
+ cmds["assertequals"] = Proc.new { |a, b|
108
+ result = (a.to_s == b)
109
+ { :result => result, :actual => a, :expected => b } }
110
+ cmds["execute"] = Proc.new { |a,b|
111
+ result = true
112
+ result = false if a.to_s =~ /Missing method/
113
+ {:result => result, :actual => a, :expected => b } }
114
+ cmds["verifyrows"] = Proc.new { |a,b| { :result => a.size == b, :actual => a.size, :expected => b } }
115
+ cmds["asserttrue"] = Proc.new { |a, b|
116
+ result = a
117
+ result = false if a.instance_of?(String)
118
+ { :result => result, :actual => false, :expected => true } }
119
+ cmds["assert_image"] = Proc.new { |actual_data, expected_image_url|
120
+ expected_data = File.read(path_for(expected_image_url))
121
+ { :result => actual_data == expected_data, :actual => "[Image data of size #{actual_data.size} omitted]", :expected => "[Expected to match #{expected_image_url}]" }
122
+ }
29
123
  cmds
30
124
  end
31
125
 
@@ -1,3 +1,5 @@
1
+ require 'concordion_utility'
2
+
1
3
  class ConcordionParseResult
2
4
  include ConcordionUtility
3
5
  attr_accessor :concordion_command, :system_under_test, :content, :tag
@@ -8,9 +10,13 @@ class ConcordionParseResult
8
10
  @tag = tag
9
11
  end
10
12
  def to_s
11
- "CPR: #{@concordion_command}, #{@system_under_test}, #{@content}"
13
+ "Concordion command[#{@concordion_command}], System under test method[#{@system_under_test}], Tag Content[#{@content}] Image Location[#{image_location}]"
12
14
  end
13
15
 
16
+ def is_assert_image_command?
17
+ "assert_image" == @concordion_command
18
+ end
19
+
14
20
  def is_set_command?
15
21
  "set" == @concordion_command
16
22
  end
@@ -20,7 +26,19 @@ class ConcordionParseResult
20
26
  def is_execute_command?
21
27
  "execute" == @concordion_command
22
28
  end
29
+ def is_assert_true_command?
30
+ "asserttrue" == @concordion_command
31
+ end
23
32
 
33
+ def num_results_expected
34
+ @tag.search("tr").size - 1
35
+ end
36
+
37
+ def image_location
38
+ return nil if @tag.nil?
39
+ @tag.get_attribute('src')
40
+ end
41
+
24
42
  def assignment
25
43
  concordion_assignment(@system_under_test)
26
44
  end
@@ -32,7 +32,7 @@ class ConcordionParser
32
32
 
33
33
  def each_eligible_concordion_element(&block)
34
34
  each_concordion_element do |elem|
35
- if concordion_cmd_attr_exists?(elem)
35
+ if concordion_cmd_attr_exists?(elem)
36
36
  attr = concordion_cmd_attr_for(elem)
37
37
  @verifier.update_row(elem)
38
38
  if !@instrumenter.instrument_from_headers(elem, attr, @root)
@@ -11,8 +11,9 @@ class ConcordionProcessor
11
11
  def process(tag, test_context)
12
12
  attr = concordion_cmd_attr_for(tag)
13
13
  instrumented_value = tag.get_attribute(attr)
14
- rv = @concordion.evaluate(create_parse_result(tag, attr, instrumented_value), test_context, self)
15
- @decorator.decorate_tag(rv, tag)
14
+ cpr = create_parse_result(tag, attr, instrumented_value)
15
+ rv = @concordion.evaluate(cpr, test_context, self)
16
+ @decorator.decorate_tag(rv, tag, cpr)
16
17
  end
17
18
 
18
19
  def create_parse_result(tag, attr, value)
@@ -34,9 +34,17 @@ module ConcordionStringUtility
34
34
  include PluralToSingularUtility
35
35
 
36
36
  def has_arguments?(name)
37
- name !~ /\(\)$/
37
+ !(ends_in_empty_parens?(name) || is_direct_method_call?(name))
38
38
  end
39
39
 
40
+ def is_direct_method_call?(name)
41
+ name =~ /^[\w]+$/
42
+ end
43
+
44
+ def ends_in_empty_parens?(name)
45
+ name =~ /\(\)$/
46
+ end
47
+
40
48
  def concordion_assignment(name)
41
49
  name.split("=")[0].strip
42
50
  end
@@ -45,19 +53,45 @@ module ConcordionStringUtility
45
53
  name =~ /=/
46
54
  end
47
55
 
48
-
56
+ def attr_writer_method?(name)
57
+ name =~ /=$/
58
+ end
59
+
49
60
  def concordion_method_name(name)
50
61
  if name =~ /\(/
51
62
  base = name.split("(")[0].strip
52
63
  else
64
+
65
+
53
66
  base = name.strip
67
+ if base =~ /\s/
68
+
69
+ if base =~ /=/ && base =~ /^#/
70
+ base = base.split("=")[1].strip
71
+ end
72
+ elements = base.split(/\s/)
73
+ base = elements[0]
74
+ end
54
75
  end
55
76
 
56
77
  if !has_assignment?(base)
57
78
  return base
58
79
  end
80
+
81
+ if attr_writer_method?(base)
82
+ return base if base.count("=") == 1
83
+ return assignment(base) + "="
84
+ end
85
+
86
+ assignment(base)
87
+ end
59
88
 
89
+ def assignment(base)
60
90
  base.split("=")[1].strip
61
91
  end
92
+
93
+ def escape_single_quotes(s)
94
+ s.gsub(/[']/, '\\\\\\\\\'')
95
+ end
62
96
 
63
97
  end
@@ -10,50 +10,26 @@ require 'concordion'
10
10
  require 'concordion_css_decorator'
11
11
  require 'test/unit'
12
12
 
13
- class ConcordionTestCase < Test::Unit::TestCase
13
+ require 'concordion_test_methods'
14
14
 
15
- @@EXPECTED_FAILURE_COUNT = 0
16
15
 
17
- include ConcordionUtility
16
+ class ConcordionTestCase < Test::Unit::TestCase
18
17
 
19
- def self.inherited(subclass)
20
- subclass.class_eval do
21
- define_method :test_spec do
22
- filename = snake_cased_test_name(subclass.to_s)
23
- parse_spec(filename)
24
- run_spec(filename)
25
- report_spec(filename)
26
- end
27
- end
28
- subclass
18
+ include ConcordionConfigMethods
19
+ extend ConcordionConfigMethods
20
+ include ConcordionInternalTestMethods
21
+ class << self
22
+ alias_method :original_inherited, :inherited
29
23
  end
30
24
 
31
- def self.default_config
32
- concordion = Concordion.new
33
- parser = ConcordionParser.new(ConcordionReader.new, concordion)
34
- decorator = ConcordionCSSDecorator.new
35
- processor = ConcordionProcessor.new(concordion, decorator)
36
- { :expected_failure_count => @@EXPECTED_FAILURE_COUNT,
37
- :parser => parser,
38
- :writer => ConcordionWriter.new(ConcordionEnvironment.output_dir),
39
- :concordion => concordion,
40
- :decorator => decorator,
41
- :processor => processor,
42
- :write_goldmaster => false,
43
- :css_type => ConcordionEnvironment.css_type
44
- }
25
+ def self.inherited(subclass)
26
+ original_inherited(subclass)
27
+ bind_test_method_to(subclass, default_config)
45
28
  end
46
29
 
47
- def initialize(arg, conf = ConcordionTestCase.default_config)
30
+ def initialize(arg, conf = default_config())
48
31
  super(arg)
49
- config = ConcordionTestCase.default_config.merge(conf)
50
- @parser = config[:parser]
51
- @writer = config[:writer]
52
- @concordion = config[:concordion]
53
- @decorator = config[:decorator]
54
- @expected_failure_count = config[:expected_failure_count]
55
- @processor = config[:processor]
56
- @css_type = config[:css_type]
32
+ @config = default_config.merge(conf)
57
33
  end
58
34
 
59
35
  def test_something_trivial_to_shut_runit_up
@@ -68,30 +44,4 @@ class ConcordionTestCase < Test::Unit::TestCase
68
44
  @trivial
69
45
  end
70
46
 
71
- def parse_spec(filename)
72
- @parser.parse(filename)
73
- assert_concordion_document
74
- @decorator.add_concordion_css_link(@parser.root, @parser.html, @css_type)
75
- end
76
-
77
- def run_spec(filename)
78
- @failures = 0
79
- @parser.each_eligible_concordion_element do |elem|
80
- @failures += @processor.process(elem, self)
81
- end
82
- end
83
-
84
- def report_spec(filename)
85
- @decorator.add_css_file_to_output_dir(@writer, @css_type)
86
- outfilename = @writer.calculate_filename_and_overwrite(@parser.root, filename)
87
- assert_no_failures(@failures, outfilename)
88
- end
89
-
90
- def assert_no_failures(failures, outfilename)
91
- assert_equal @expected_failure_count, failures, "Wrote output to #{outfilename}"
92
- end
93
-
94
- def assert_concordion_document
95
- assert_equal "http://www.concordion.org/2007/concordion", @parser.html.get_attribute("xmlns:concordion")
96
- end
97
47
  end