File: test_unit_heckler.rb

package info (click to toggle)
ruby-heckle 1.4.3-4
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 240 kB
  • sloc: ruby: 1,486; sh: 45; makefile: 11
file content (126 lines) | stat: -rw-r--r-- 3,101 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/env ruby

require 'test/unit/autorunner'
require 'test/unit/testcase'
require 'heckle'
begin
  require 'zentest_mapping'
  HAVE_ZENTEST = true
rescue LoadError
  # if zentest isn't available, just don't use it
  HAVE_ZENTEST = false
end

$: << 'lib' << 'test'

# Make sure test/unit doesn't swallow our timeout
begin
  Test::Unit::TestCase::PASSTHROUGH_EXCEPTIONS << Heckle::Timeout
rescue NameError
  # ignore
end

class TestUnitHeckler < Heckle

  @@test_pattern = 'test/test_*.rb'
  @@tests_loaded = false
  @@focus = false

  def self.test_pattern=(value)
    @@test_pattern = value
  end

  def self.focus=(value)
    @@focus = value
  end

  def self.load_test_files
    @@tests_loaded = true
    Dir.glob(@@test_pattern).each {|test| require test}
  end

  def self.validate(klass_name, method_name = nil,
                    nodes = Heckle::MUTATABLE_NODES, force = false)
    load_test_files
    klass = klass_name.to_class

    # Does the method exist?
    klass_methods = klass.singleton_methods(false).collect {|meth| "self.#{meth}"}
    if method_name
      if method_name =~ /self\./
        abort "Unknown method: #{klass_name}.#{method_name.gsub('self.', '')}" unless klass_methods.include? method_name
      else
        abort "Unknown method: #{klass_name}##{method_name}" unless klass.instance_methods(false).include? method_name
      end
    end

    initial_time = Time.now

    heckle = self.new(klass_name)

    passed = heckle.tests_pass?

    unless force or passed then
      abort "Initial run of tests failed... fix and run heckle again"
    end

    if self.guess_timeout? then
      running_time = Time.now - initial_time
      adjusted_timeout = (running_time * 2 < 5) ? 5 : (running_time * 2).ceil
      self.timeout = adjusted_timeout
    end

    puts "Timeout set to #{adjusted_timeout} seconds."

    if passed then
      puts "Initial tests pass. Let's rumble."
    else
      puts "Initial tests failed but you forced things. Let's rumble."
    end
    puts

    methods = method_name ? Array(method_name) : klass.instance_methods(false) + klass_methods

    counts = Hash.new(0)
    methods.sort.each do |method_name|
      result = self.new(klass_name, method_name, nodes).validate
      counts[result] += 1
    end
    all_good = counts[false] == 0

    puts "Heckle Results:"
    puts
    puts "Passed    : %3d" % counts[true]
    puts "Failed    : %3d" % counts[false]
    puts "Thick Skin: %3d" % counts[nil]
    puts

    if all_good then
      puts "All heckling was thwarted! YAY!!!"
    else
      puts "Improve the tests and try again."
    end

    all_good
  end

  def initialize(klass_name=nil, method_name=nil, nodes=Heckle::MUTATABLE_NODES)
    super
    self.class.load_test_files unless @@tests_loaded
  end

  include ZenTestMapping if HAVE_ZENTEST

  def tests_pass?
    silence_stream do
      if @@focus and @method_name then
        name = normal_to_test @method_name.to_s
        ARGV.clear
        ARGV << "--name=/#{name}/"
      end
      result = Test::Unit::AutoRunner.run
      ARGV.clear
      result
    end
  end
end