class Given::NaturalAssertion
Constants
- VOID_SEXP
- WRAP_WIDTH
Public Class Methods
new(clause_type, block, example, line_extractor)
click to toggle source
# File lib/given/natural_assertion.rb 26 def initialize(clause_type, block, example, line_extractor) 27 @clause_type = clause_type 28 @evaluator = Evaluator.new(example, block) 29 @line_extractor = line_extractor 30 set_file_and_line(block) 31 end
Public Instance Methods
has_content?()
click to toggle source
# File lib/given/natural_assertion.rb 35 def has_content? 36 return true unless NATURAL_ASSERTIONS_SUPPORTED 37 assertion_sexp != VOID_SEXP 38 end
message()
click to toggle source
# File lib/given/natural_assertion.rb 40 def message 41 @output = "#{@clause_type} expression failed at #{source_line}\n" 42 if NATURAL_ASSERTIONS_SUPPORTED 43 @output << "Failing expression: #{source.strip}\n" if @clause_type != "Then" 44 explain_failure 45 display_pairs(expression_value_pairs) 46 @output << "\n" 47 else 48 @output << "Failing expression (possibly truncated): #{source.strip}\n" 49 end 50 @output 51 end
Private Instance Methods
adjust_indentation(string)
click to toggle source
# File lib/given/natural_assertion.rb 170 def adjust_indentation(string) 171 string.to_s.gsub(/^/, ' ') 172 end
assertion_sexp()
click to toggle source
# File lib/given/natural_assertion.rb 79 def assertion_sexp 80 @assertion_sexp ||= extract_test_expression(Ripper::SexpBuilder.new(source).parse) 81 end
assertion_subexpressions()
click to toggle source
# File lib/given/natural_assertion.rb 75 def assertion_subexpressions 76 Sorcerer.subexpressions(assertion_sexp).reverse.uniq.reverse 77 end
contains_multiple_statements?(block_sexp)
click to toggle source
# File lib/given/natural_assertion.rb 130 def contains_multiple_statements?(block_sexp) 131 !(delve(block_sexp,2,0) == :stmts_add && 132 delve(block_sexp,2,1,0) == :stmts_new) 133 end
delve(ary, *indicies)
click to toggle source
Safely dive into an array with a list of indicies. Return nil if the element doesn't exist, or if the intermediate result is not indexable.
# File lib/given/natural_assertion.rb 142 def delve(ary, *indicies) 143 result = ary 144 while !indicies.empty? && result 145 return nil unless result.respond_to?(:[]) 146 i = indicies.shift 147 result = result[i] 148 end 149 result 150 end
display_pairs(pairs)
click to toggle source
# File lib/given/natural_assertion.rb 159 def display_pairs(pairs) 160 width = suggest_width(pairs) + 4 161 pairs.each do |x, v| 162 v = adjust_indentation(v) 163 fmt = multi_line?(v) ? 164 "%-#{width}s\n#{' '*width} <- %s\n" : 165 "%-#{width}s <- %s\n" 166 @output << sprintf(fmt, v, x) 167 end 168 end
eval_sexp(sexp)
click to toggle source
# File lib/given/natural_assertion.rb 152 def eval_sexp(sexp) 153 expr_string = Sorcerer.source(sexp) 154 @evaluator.eval_string(expr_string) 155 end
explain_expected(expect_msg, expect_sexp, got_msg, got_sexp)
click to toggle source
# File lib/given/natural_assertion.rb 62 def explain_expected(expect_msg, expect_sexp, got_msg, got_sexp) 63 width = [expect_msg.size, got_msg.size].max 64 sprintf("%#{width}s: %s\n%#{width}s: %s\n", 65 expect_msg, eval_sexp(expect_sexp), 66 got_msg, eval_sexp(got_sexp)) 67 end
explain_failure()
click to toggle source
# File lib/given/natural_assertion.rb 55 def explain_failure 56 binary = BinaryOperation.parse(assertion_sexp) 57 if binary && binary.explain 58 @output << explain_expected("expected", binary.left, binary.explain, binary.right) 59 end 60 end
expression_value_pairs()
click to toggle source
# File lib/given/natural_assertion.rb 69 def expression_value_pairs 70 assertion_subexpressions.map { |exp| 71 [exp, @evaluator.eval_string(exp)] 72 } 73 end
extract_brace_block(sexp)
click to toggle source
# File lib/given/natural_assertion.rb 97 def extract_brace_block(sexp) 98 unless then_block?(sexp) 99 source = Sorcerer.source(sexp) 100 fail InvalidThenError, "Unexpected code at #{source_line}\n#{source}" 101 end 102 sexp[1][2][2] 103 end
extract_first_statement(block_sexp)
click to toggle source
# File lib/given/natural_assertion.rb 122 def extract_first_statement(block_sexp) 123 if contains_multiple_statements?(block_sexp) 124 source = Sorcerer.source(block_sexp) 125 fail InvalidThenError, "Multiple statements in Then block at #{source_line}\n#{source}" 126 end 127 extract_statement_from_block(block_sexp) 128 end
extract_statement_from_block(block_sexp)
click to toggle source
# File lib/given/natural_assertion.rb 135 def extract_statement_from_block(block_sexp) 136 delve(block_sexp,2,2) 137 end
extract_test_expression(sexp)
click to toggle source
# File lib/given/natural_assertion.rb 92 def extract_test_expression(sexp) 93 brace_block = extract_brace_block(sexp) 94 extract_first_statement(brace_block) 95 end
has_block_sexp?(sexp)
click to toggle source
# File lib/given/natural_assertion.rb 118 def has_block_sexp?(sexp) 119 delve(sexp,1,2,2,0) == :brace_block || delve(sexp,1,2,2,0) == :do_block 120 end
max_line_length(string)
click to toggle source
# File lib/given/natural_assertion.rb 184 def max_line_length(string) 185 string.to_s.split(/\n/).map { |s| s.size }.max 186 end
method_with_block?(sexp)
click to toggle source
# File lib/given/natural_assertion.rb 113 def method_with_block?(sexp) 114 delve(sexp,1,0) == :stmts_add && 115 delve(sexp,1,2,0) == :method_add_block 116 end
multi_line?(string)
click to toggle source
# File lib/given/natural_assertion.rb 174 def multi_line?(string) 175 (string.size > WRAP_WIDTH) || (string =~ /\n/) 176 end
program_sexp?(sexp)
click to toggle source
# File lib/given/natural_assertion.rb 109 def program_sexp?(sexp) 110 delve(sexp,0) == :program 111 end
set_file_and_line(block)
click to toggle source
# File lib/given/natural_assertion.rb 87 def set_file_and_line(block) 88 @code_file, @code_line = @evaluator.location 89 @code_line = @code_line.to_i 90 end
source()
click to toggle source
# File lib/given/natural_assertion.rb 83 def source 84 @source ||= @line_extractor.line(@code_file, @code_line) 85 end
source_line()
click to toggle source
# File lib/given/natural_assertion.rb 188 def source_line 189 "#{@code_file}:#{@code_line}" 190 end
suggest_width(pairs)
click to toggle source
# File lib/given/natural_assertion.rb 178 def suggest_width(pairs) 179 pairs.map { |x,v| 180 max_line_length(v) 181 }.select { |n| n < WRAP_WIDTH }.max || 10 182 end
then_block?(sexp)
click to toggle source
# File lib/given/natural_assertion.rb 105 def then_block?(sexp) 106 program_sexp?(sexp) && method_with_block?(sexp) && has_block_sexp?(sexp) 107 end