Module: Yamltest::ClassMethods

Defined in:
lib/yamltest.rb

Instance Method Summary collapse

Instance Method Details

#file_list(caller_path, opts) ⇒ Object

build an array of file_name, file_path, options



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
# File 'lib/yamltest.rb', line 16

def file_list(caller_path, opts)
  directories = opts[:directories] || [opts[:directory] || :default]

  if files = opts[:files]
    files.map!{|f| f.to_s}
  end

  directories = directories.map do |dir|
    if dir == :default
      if caller_path.split('/').last =~ /^(.*)_test.rb/ || caller_path.split('/').last =~ /^test_(.*).rb/
        directories = [File.join(File.dirname(caller_path), $1)]
      else
        puts "Bad file name for yaml_tests '#{caller_path}'. Should be 'xxx_test.rb' or 'test_xxx.rb'. Trying parent directory."
        directories = [File.dirname(caller_path)]
      end
    else
      # GLOB absolute path
      list = Dir[dir]
      if list.empty?
        # relative to caller
        list = Dir[File.join(File.dirname(caller_path),dir)]
      end
      list
    end
  end.flatten.uniq

  file_list = []

  directories.each do |dir|
    Dir.foreach(dir) do |f|
      next unless f =~ /^([\w_-]+).yml/
      next if files && !files.include?($1)
      file_list << [$1, File.join(dir, "#{$1}.yml"), opts[$1] || opts[$1.to_sym] || {}]
    end
  end

  file_list
end

#yamltest(opts = {}) ⇒ Object

Setup yaml testing. usage: class SuperTest < Test::Unit::TestCase

yamltest

or to define custom search directories for tests definitions class SuperTest < Test::Unit::TestCase

yamltest :directories => ["sub/**", "/absolute/location"]

to use only some files: class SuperTest < Test::Unit::TestCase

yamltest :files => ["one", "two"]

to pass parameters during testing of a specific file: class SuperTest < Test::Unit::TestCase

yamltest :options => {:latex => {:module => Latex}}


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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/yamltest.rb', line 73

def yamltest(opts = {})
  # We need to do a class_eval so that the class variables 'test_strings, test_methods, ...' are scoped
  # in the final class and are not global to all tests using the YamlTest helper.
  # TODO: we could use the singleton accessor:
  # class << self
  #   attr_accessor test_strings
  # end
  # and then use "self.test_strings"

  class_eval %Q{
    @@test_strings = {}
    @@test_methods = {}
    @@test_options = {}
    @@test_files = []
    @@file_list  = file_list(#{caller[0].inspect}, #{opts.inspect})

    @@file_list.each do |file_name, file_path, opts|
      strings = {}
      test_methods = []
      begin
        YAML::load_documents( File.open( file_path ) ) do |doc|
          doc.each do |elem|
            test_methods << elem[0]
            strings[elem[0]] = elem[1]
          end
        end
      rescue ArgumentError => err
        puts "Error while loading test file \#{file_path}"
        raise err
      end
      class_eval "
        def \#{file_name}_tests
          @@test_strings['\#{file_name}']
        end
      "
      @@test_strings[file_name] = strings.freeze
      @@test_methods[file_name] = test_methods
      @@test_files << file_name
    end

    # Override this in your test class
    def yt_parse(key, source, context)
      source
    end

    def yt_do_test(file, test, context = yt_get('context',file,test))
      @@test_strings[file][test].keys.each do |key|
        next if ['src', 'context'].include?(key)
        yt_assert yt_get(key,file,test), yt_parse(key, yt_get('src',file,test), context)
      end
    end

    protected
      def yt_assert(test_res, res)
        if test_res.kind_of?(String) && test_res[0..1] == '!/'
          assert_no_match %r{\#{test_res[2..-2]}}m, res
        elsif test_res.kind_of?(String) && test_res[0..0] == '/'
          assert_match %r{\#{test_res[1..-2]}}m, res
        else
          assert_equal test_res, res
        end
      end

      def yt_get(key, file, test)
        case key
        when 'context', :context
          context = @@test_strings[file][test]['context'] || {}
          default_context = (@@test_strings[file]['default'] || {})['context'] || {}
          context = default_context.merge(context)
        when 'src'
          @@test_strings[file][test]['src'] #{opts[:src_from_title] != false ? "|| (test.gsub('_',' '))" : ''}
        else
          @@test_strings[file][test][key.to_s]
        end
      end
  }
end

#yt_makeObject



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/yamltest.rb', line 151

def yt_make
  class_eval %q{
    return unless @@test_methods
    tests = self.instance_methods.reject! {|m| !( m =~ /^test_/ )}
    @@test_files.each do |tf|
      @@test_methods[tf].each do |test|
        unless tests.include?(:"test_#{tf}_#{test}")
          tests << "test_#{tf}_#{test}"
          class_eval <<-END
            def test_#{tf}_#{test.gsub(/[^_a-zA-Z]/, '_')}
              yt_do_test(#{tf.inspect}, #{test.inspect})
            end
          END
        end
      end
    end
  }
end