Class: Test::Unit::TestCase

Inherits:
Object
  • Object
show all
Defined in:
lib/more_unit_test/assert_stdout.rb,
lib/more_unit_test/assert_equal_filecontent.rb

Overview

Extend the class TestCase with additional methods/assertions:

  • Test::Unit::TestCase#assert_equal_filecontent

Constant Summary collapse

FOLDER_FOR_FAILURE =

Default path in case of an error.

"failure_#{Date.today}"

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#folder_for_failure=(value) ⇒ Object (writeonly)

Default path in case of an error. Overwrites FOLDER_FOR_FAILURE. With ‘false’ no file is written



45
46
47
# File 'lib/more_unit_test/assert_equal_filecontent.rb', line 45

def folder_for_failure=(value)
  @folder_for_failure = value
end

#read_encoding=(value) ⇒ Object (writeonly)

Overwrite encoding of ‘expected’ file. Needed for each test method.



48
49
50
# File 'lib/more_unit_test/assert_equal_filecontent.rb', line 48

def read_encoding=(value)
  @read_encoding = value
end

Instance Method Details

#assert_equal_filecontent(filename, actual, message = nil) ⇒ Object

Takes the content of the file ‘filename’ and compares it with ‘actual’ like in assert_equal. If ‘filename’ doesn’t exist, the failure

Reference file <#{filename}> missing

is returned.

‘folder_for_failure’ will contain all results with differences.

Example of the usage:

assert_equal_filecontent( "expected/test_section.html", 
                          text.to_doc(:html), 
                          'short description of test'
                        )

What will happen:

  1. text.to_doc(:html) is the test. It creates some HTML-Text

  2. “expected/test_section.html” is read and compared to text.to_doc(:html)

    1. If the file is missing -> error

    2. If it is the same -> fine

    3. If there are differences:

  3. A message is given (like in assert_equal)

  4. A folder “failure_#Date.today” is created if not already exist (See FOLDER_FOR_FAILURE )

  5. The file ‘test_section.html’ with the result is created in FOLDER_FOR_FAILURE

  6. You can use a compare tool to compare the expected result and the real result.

If you don’t want a failure file (step 4 and 5), you may suppress it with:

def text_no_failure file
  self.folder_for_failure = false  #inactivate error/reference file creation.
  #...
end

filename

The filename may contains some parameters in <x>. Details see Test::Unit::TestCase#build_filename

Recommendation to build up your test.

  1. Define your tests with your assertions.

  2. Run the test

  3. You will get errors ‘Reference file <xx/not_available.txt> missing’

and a directory 'failure_<date>
  1. Rename the folder ‘failure’ to ‘expected’

  2. Check, if the content of the folder is the wanted result.

  3. Rerun again, you have no failure (hopefully ;-) )

If you already have the result, you may start like this:

  1. Create a folder: ‘expected’

  2. Define your assertion with non-existing filename in the ‘expected’-folder.

  3. Copy the expected results to the ‘expected’-folder.

  4. Run the test

  5. In case of errors:

Compare the content of the ‘expected’-folder with the failure-folder. Adapt your code or your expected result.

  1. Rerun again, until you get the expected results



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/more_unit_test/assert_equal_filecontent.rb', line 104

def assert_equal_filecontent( filename, actual, message = nil )
  #

  filename = build_filename(filename)
    #Set encoding, if actual includes encoding-info.

  encoding = Encoding.default_external 
  encoding = actual.encoding if actual.respond_to?(:encoding)
  encoding = @read_encoding if @read_encoding #encoding was overwritten

  
  #Make the tests

  if File.exist?(filename)
    #~ expected = File.read(filename) 

    expected = nil
    File.open(filename, 'r', :encoding => encoding ){|file| expected = file.read }
    #~ full_message = build_message(message, "<?> expected (#{filename}) but was\n<?>.\n", expected, actual).to_s

    full_message = '' #main message build from assert_equal

  else
    full_message = "Reference file <#{filename}> missing"
  end

  #Write the real result to a file if a failure folder is given.

  if @folder_for_failure != false and expected  != actual
    folder_for_failure = @folder_for_failure || FOLDER_FOR_FAILURE 
    FileUtils.makedirs(folder_for_failure) unless File.directory?(folder_for_failure)
    File.open( "#{folder_for_failure}/#{File.basename(filename)}", 'w', :encoding => encoding){|f|
      f << actual
    }
    full_message << "\n\t-> Build <#{folder_for_failure}/#{File.basename(filename)}>"
  end

  #Will not work with Ruby 1.9.1/1.9.2. 

  # -> assert( false, full_message  )

  if File.exist?(filename)
    #Use the standard assertion to get the layouted message.

    assert_equal( expected, actual, "Result differs to file content #{filename}" + full_message )
    #~ assert_block( full_message ){ expected  == actual }

  else
    assert_block( full_message ){ false }
    #~ assert_equal( expected, actual, full_message )

  end
end

#assert_stderr(expected, actual, message = nil) ⇒ Object

Compare the stderr-output with your exception.

Actual must be a procedure. Another object (like a method call) would be executed first, before stderr could be redirected.

Example:

require 'assert_stdout'
def puts_err( arg )
  $stderr << arg
end

class MyTest < Test::Unit::TestCase  
  def test_hello_world()
    assert_stderr("Hello World", Proc.new{ puts_err 'Hello World'} )
  end
end


129
130
131
132
133
134
135
136
137
138
139
# File 'lib/more_unit_test/assert_stdout.rb', line 129

def assert_stderr( expected, actual, message = nil )
  if actual.respond_to?(:call)
    output = catch_stderr( actual )
    full_message = build_message(message, "<?> expected in stderr, but was\n<?>.\n", expected, output)
    assert_block( full_message ){ expected  == output }
  else
    raise 'no Proc-object given'
    full_message = build_message(message, "<?> expected in stderr, but no Proc-object is given to test.\n", expected )
    assert_block( full_message ){ false } #force error

  end
end

#assert_stderr_block(expected, message = nil) ⇒ Object

Compare the stderr-output with your exception.

Example:

require 'assert_stdout'
def puts_err( arg )
  $stderr << arg
end

class MyTest < Test::Unit::TestCase  
  def test_hello_world()
    assert_stderr_block("Hello World"){ puts_err 'Hello World'}
  end
end


155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/more_unit_test/assert_stdout.rb', line 155

def assert_stderr_block( expected, message = nil )
  if block_given? 
    $stderr = output = Catch_IO.new #temporary copy

    yield
    $stderr = STDERR
    full_message = build_message(message, "<?> expected in stderr, but was\n<?>.\n", expected, output)
    assert_block( full_message ){ expected  == output }
  else
    raise 'no block given'
    full_message = build_message(message, "<?> expected in stderr, but no block to test.\n", expected )
    assert_block( full_message ){ false }
  end
end

#assert_stdout(expected, actual, message = nil) ⇒ Object

Compare the stdout-output with your exception.

Actual must be a procedure.
Another object (like a method call) would be executed first, before stdout could be redirected.

Example:
    require 'assert_stdout'
    class MyTest < Test::Unit::TestCase  
      def test_hello_world()
        assert_stdout("Hello World\n", Proc.new{ puts 'Hello World'} )
      end
    end


63
64
65
66
67
68
69
70
71
72
73
# File 'lib/more_unit_test/assert_stdout.rb', line 63

def assert_stdout( expected, actual, message = nil )
  if actual.respond_to?(:call)
    output = catch_stdout( actual )
    full_message = build_message(message, "<?> expected in stdout, but was\n<?>.\n", expected, output)
    assert_block( full_message ){ expected  == output }
  else
    raise 'no Proc-object given'
    full_message = build_message(message, "<?> expected in stdout, but no Proc-object is given to test.\n", expected )
    assert_block( full_message ){ false } #force error

  end
end

#assert_stdout_block(expected, message = nil) ⇒ Object

Compare the stdout-output of a given block with your exception.

Example:

require 'assert_stdout'
class MyTest < Test::Unit::TestCase  
  def test_hello_world()
    assert_stdout_block("Hello World\n"){ puts 'Hello World'}
  end
end


85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/more_unit_test/assert_stdout.rb', line 85

def assert_stdout_block( expected, message = nil )
  previous_stdout = $stdout
  previous_STDOUT = STDOUT
  if block_given? 
    $stdout = output = Catch_IO.new #temporary copy

    #~ STDOUT.reopen($stdout)

    yield
    $stdout = previous_stdout
    #~ STDOUT.reopen(previous_STDOUT)

    full_message = build_message(message, "<?> expected in stdout, but was\n<?>.\n", expected, output)
    assert_block( full_message ){ expected  == output }
  else
    raise 'no block given'
    full_message = build_message(message, "<?> expected in stdout, but no block to test.\n", expected )
    assert_block( full_message ){ false }
  end
end

#build_filename(filename, level = 1) ⇒ Object

Make filename conversion.

The filename may contains some parameters in <x>. x may be:

  • c - test class name

  • m - methodname from caller

  • cm - test class name - methodname

Parameter ‘level’ is needed to get the method.

Example:

class MyTest < Test::Unit::TestCase
  def test_xx
    assert_equal_filecontent( "<m>.txt", mycode )
  end
end

The caller stack will be

___lib/more_unit_test/assert_equal_filecontent.rb:112:in `assert_equal_filecontent'
quicktest.rb:13:in `test_xx'
___test-unit-2.4.0/lib/test/unit/testcase.rb:531:in `run_test'

The result with default level 1 is ‘test_xx’ - the method from your test.



170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/more_unit_test/assert_equal_filecontent.rb', line 170

def  build_filename(filename, level = 1)
  method = caller[level].match(/^(.+?):(\d+)(?::in `(.*)')?/)[3]  #methodname

  filename.gsub(/<.*?>/){ |hit|
    case hit
      when '<c>'; self.class.name
      when '<m>'; method
      when '<cm>'; "#{self.class}-#{method}" #methodname

      else; raise ArgumentError, "Undefined option #{hit} in filename #{filename}"
    end
  }.sub(/block (\(\d+ levels\) )?in /,'')
  
end

#catch_stderr(procedure) ⇒ Object

Catch stderr for a given procedure (Proc-Element).



105
106
107
108
109
110
# File 'lib/more_unit_test/assert_stdout.rb', line 105

def catch_stderr( procedure )
  $stderr = output = Catch_IO.new #temporary copy

  procedure.call
  $stderr = STDERR
  output
end

#catch_stdout(procedure) ⇒ Object

Catch stdout for a given procedure (Proc-Element).



43
44
45
46
47
48
# File 'lib/more_unit_test/assert_stdout.rb', line 43

def catch_stdout( procedure )
  $stdout = output = Catch_IO.new #temporary copy

  procedure.call
  $stdout = STDOUT
  output
end