root/trunk/lib/yaml_test.rb

Revision 1259, 4.6 kB (checked in by gaspard, 2 months ago)

commit 5c1378c03854bd32ed765a941cdd187647bc51fd
Author: Gaspard Bucher <gaspard@teti.ch>

typos

Line 
1 require 'test/unit'
2 require 'yaml'
3
4 module YamlTest
5   module Helper
6     def self.included(obj)
7       obj.extend YamlTest::ClassMethods
8     end
9   end
10  
11   module ClassMethods
12    
13     # build an array of file_name, file_path, options
14     def file_list(caller_dir, opts)
15       directories = opts[:directories] || [:default]
16      
17       if files = opts[:files]
18         files.map!{|f| f.to_s}
19       end
20      
21       directories = directories.map do |dir|
22         if dir == :default
23           if caller_dir.split('/').last =~ /^(.*)_test.rb/
24             directories = [File.join(File.dirname(caller_dir), $1)]
25           else
26             puts "Bad file name for yaml_tests '#{caller_dir}'. Should be '..._test.rb'. Trying parent directory."
27             directories = [File.dirname(caller_dir)]
28           end
29         else
30           Dir[dir]
31         end
32       end.flatten
33
34       file_list = []
35      
36       directories.each do |dir|
37         Dir.foreach(dir) do |f|
38           next unless f =~ /^([\w_-]+).yml/
39           next if files && !files.include?($1)
40           file_list << [$1, File.join(dir, "#{$1}.yml"), opts[$1] || opts[$1.to_sym] || {}]
41         end
42       end
43      
44       file_list
45     end
46    
47    
48     # Setup yaml testing.
49     # usage:
50     # class SuperTest < Test::Unit::TestCase
51     #   yaml_test
52     #
53     # or to define custom search directories for tests definitions
54     # class SuperTest < Test::Unit::TestCase
55     #   yaml_test :directories => ["sub/**", "/absolute/location"]
56     #
57     # to use only some files:
58     # class SuperTest < Test::Unit::TestCase
59     #   yaml_test :files => ["one", "two"]
60     #
61     # to pass parameters during testing of a specific file:
62     # class SuperTest < Test::Unit::TestCase
63     #   yaml_test :options => {:latex => {:module => Latex}}
64     #
65     def yaml_test(opts = {})
66       # We need to do a class_eval so that the class variables 'test_strings, test_methods, ...' are scoped
67       # in the final class and are not global to all tests using the YamlTest helper.
68       
69       class_eval %Q{
70         @@test_strings = {}
71         @@test_methods = {}
72         @@test_options = {}
73         @@test_files = []
74         @@file_list  = file_list(#{caller[0].inspect}, #{opts.inspect})
75        
76         @@file_list.each do |file_name, file_path, opts|
77           strings = {}
78           test_methods = []
79           begin
80             YAML::load_documents( File.open( file_path ) ) do |doc|
81               doc.each do |elem|
82                 test_methods << elem[0]
83                 strings[elem[0]] = elem[1]
84               end
85             end
86           rescue ArgumentError => err
87             puts "Error while loading test file \#{file_path}"
88             raise err
89           end
90           class_eval "
91             def \#{file_name}
92               @@test_strings['\#{file_name}']
93             end
94           "
95           @@test_strings[file_name] = strings.freeze
96           @@test_methods[file_name] = test_methods
97           @@test_files << file_name
98         end
99        
100         # Override this in your test class
101         def parse(key, source, context)
102           source
103         end
104        
105         def do_test(file, test)
106           context = @@test_strings[file][test]['context'] || {}
107           default_context = (@@test_strings[file]['default'] || {})['context'] || {}
108           context = Hash[*default_context.merge(context).map{|k,v| [k.to_sym,v]}.flatten]
109           @@test_strings[file][test].keys.each do |key|
110             next if ['src', 'context'].include?(key)
111             assert_yaml_test @@test_strings[file][test][key], parse(key, @@test_strings[file][test]['src'] || test.gsub('_',' '), context)
112           end
113         end
114        
115         protected
116           def assert_yaml_test(test_res, res)
117             if test_res.kind_of?(String) && test_res[0..1] == '!/'
118               assert_no_match %r{\#{test_res[2..-2]}}m, res
119             elsif test_res.kind_of?(String) && test_res[0..0] == '/'
120               assert_match %r{\#{test_res[1..-2]}}m, res
121             else
122               assert_equal test_res, res
123             end
124           end
125       }
126     end
127    
128     def make_tests
129       class_eval %q{
130         return unless @@test_methods
131         tests = self.instance_methods.reject! {|m| !( m =~ /^test_/ )}
132         @@test_files.each do |tf|
133           @@test_methods[tf].each do |test|
134             unless tests.include?("test_#{tf}_#{test}")
135               tests << "test_#{tf}_#{test}"
136               class_eval <<-END
137                 def test_#{tf}_#{test}
138                   do_test(#{tf.inspect}, #{test.inspect})
139                 end
140               END
141             end
142           end
143         end
144       }
145     end
146   end
147 end
148
149 Test::Unit::TestCase.send :include, YamlTest::Helper
Note: See TracBrowser for help on using the browser.