OSDN Git Service

refactored spec for square_root_arithmetic generator
[mint/mint-lib.git] / spec / spec_helper.rb
1 # -*- coding: utf-8 -*-
2
3 $:.unshift File.dirname(__FILE__) + '/../lib'
4 require 'mint'
5
6 Spec::Matchers.define :have_certain_param do |name, value|
7   match do |object|
8     object.instance_variable_get(name) == value
9   end
10 end
11
12 shared_examples_for 'generator' do
13   it do
14     subject.should_receive(:setup).
15       exactly(1).times.with(no_args)
16     subject.should_receive(:generate_problem).
17       exactly(1).times.and_return('problem')
18     subject.should_receive(:teardown).
19       exactly(1).times.with('problem')
20     subject.stub(:validation_loop) {|r| r }
21     subject.generate.should have(1).problems
22   end
23
24   context 'options' do
25
26     before do
27       @options = { :range => (5..10) }
28       @defaults = [
29         [:test1, 'test1'],
30         [:test2, 'test2'],
31         [:test3, 'test3'],
32       ]
33
34       klass = subject.class
35       klass.__send__(:option, *@defaults[0])
36       klass.__send__(:option, *@defaults[1])
37       klass.__send__(:option, *@defaults[2])
38
39       subject.__send__(:options=, @options)
40     end
41
42     context 'set defaults' do
43       before { @default_options = subject.class.__send__(:class_variable_get, :@@default_options) }
44       it { @default_options.should include(*@defaults.map(&:first)) }
45     end
46
47     context 'refer' do
48       before { @opts = subject.__send__(:options) }
49       it { @opts.should include(:range) }
50       it { @opts.should include(:test1) }
51       it { @opts.should include(:test2) }
52       it { @opts.should include(:test3) }
53       it { @opts[:range].should == @options[:range] }
54       it { @opts[:test1].should == @defaults.assoc(:test1)[1] }
55       it { @opts[:test2].should == @defaults.assoc(:test2)[1] }
56       it { @opts[:test3].should == @defaults.assoc(:test3)[1] }
57     end
58   end
59 end
60
61 shared_examples_for 'Arithmetic' do
62
63     def set_options(options = {})
64       defaults = {:term_number => 1, :operators => ['@']}
65       subject.__send__(:options=, defaults.merge(options))
66     end
67
68     before { set_options }
69
70     it_should_behave_like 'generator'
71
72     [
73       [' -25', ' (-25)'],
74       ['-25', '-25'],
75       [' 25', ' 25'],
76       ['       -25', '       (-25)'],
77
78     ].each do |from, to|
79       it do
80         subject.__send__(:teardown, from).should == to
81       end
82     end
83
84     [
85       [:factor, 5],
86       [:spec, 10],
87       [:hoge, 12],
88       [:zero, 0],
89
90     ].each do |position, term_number|
91       context position do
92         before do
93           options = {
94             :"#{position}_term_min" => term_number,
95             :"#{position}_term_max" => term_number,
96           }
97           subject.stub(:options => options)
98         end
99         it { subject.__send__(:term_number, position).should == term_number }
100       end
101     end
102
103     context 'operand' do
104
105       before(:all) do
106         @msg ='This operand need these options:'
107         @int = '1'
108         subject.stub(:create_integer => 1)
109       end
110
111       context 'integer' do
112         before { set_options(:min => nil, :max => nil, :minus => nil) }
113         it { subject.__send__(:integer).should == @int }
114       end
115
116       context 'decimal' do
117         before do
118           set_options(
119             :min    => nil,
120             :max    => nil,
121             :minus  => nil,
122             :digits => 2
123           )
124         end
125         it { subject.__send__(:decimal).should match(/(?:#{@int}|0)\.\d\d?/) }
126       end
127
128       context 'fraction' do
129         before do
130           set_options(
131             :numerator_min   => nil,
132             :numerator_max   => nil,
133             :denominator_min => nil,
134             :denominator_max => nil,
135             :minus           => nil
136           )
137           subject.should_receive(:numerator_part).and_return('a')
138           subject.should_receive(:denominator_part).and_return('b')
139         end
140         it { subject.__send__(:fraction).should == "a/b" }
141       end
142     end
143 end
144
145 module ProblemExamples
146
147   def self.get(*types)
148     types.inject([]) {|memo, type|
149       memo += __send__(type) }
150   end
151
152   private
153   def self.existing
154     [
155       ['7 / 12 + 17 / 12', '7 / 12 + 17 / 12'],
156       ['3 / 4 + 1 / 7', '3 / 4 + 1 / 7'],
157       ['2 / 9 - 3 / 5', '2 / 9 - 3 / 5'],
158       ['2', '2'],
159       ['4/11', '4 / 11'],
160       ['25/28', '25 / 28'],
161       ['-7/12', '-7 / 12'],
162       ['-17/45','-17 / 45' ],
163       ['(2a + 1)(3a - 2)', '(2 * a + 1) * (3 * a - 2)'],
164       ['(x + 2)^2', '(x + 2)^2'],
165       ['(3P - 2Q)^3', '(3 * P - 2 * Q)^3'],
166       ['1 / (x + 1)(x + 2)', '1 / ((x + 1) * (x + 2))'],
167       ['2x^3 + x - 1', '2 * x^3 + x - 1'],
168       ['(X^2 - Y^2)', '(X^2 - Y^2)'],
169       ['root(2)root(8)', 'sqrt(2) * sqrt(8)'],
170       ['sqrt(2)sqrt(8)', 'sqrt(2) * sqrt(8)'],
171       ['(1 + root(3))(2 - root(3))', '(1 + sqrt(3)) * (2 - sqrt(3))'],
172       ['(1 + sqrt(3))(2 - sqrt(3))', '(1 + sqrt(3)) * (2 - sqrt(3))'],
173       ['1 / root(2)', '1 / sqrt(2)'],
174       ['1 / sqrt(2)', '1 / sqrt(2)'],
175       ['2 / (root(3) - 1)', '2 / (sqrt(3) - 1)'],
176       ['2 / (sqrt(3) - 1)', '2 / (sqrt(3) - 1)'],
177     ]
178   end
179
180   def self.original
181     [
182       ['1 + 1', '1 + 1'],
183       ['2 - 2', '2 - 2'],
184       ['3 * 3', '3 * 3'],
185       ['4 / 4', '4 / 4'],
186       ['5 div 5', '5 div 5'],
187       ['-233/23', '-233 / 23'],
188       ['(x^2 + 4)(y^3 - 2)', '(x^2 + 4) * (y^3 - 2)'],
189       ['(x^3 + 2)(x^2- 3)', '(x^3 + 2) * (x^2 - 3)'],
190       ['2(x^2 + xy + y^2)', '2 * (x^2 + x * y + y^2)'],
191       ['sqrt(2(x^(2 + 3) + xyz^5 + y^2))', 'sqrt(2 * (x^(2 + 3) + x * y * z^5 + y^2))'],
192       ['sqrt(2(x^(2 + 3) + root(xyz^5) + y^2))', 'sqrt(2 * (x^(2 + 3) + sqrt(x * y * z^5) + y^2))'],
193       ['5xc*1div5 + 1 (34 - 1 /8 + 1)', '5 * x * c * 1 div 5 + 1 * (34 - 1 / 8 + 1)'],
194       ['2PI', '2 * %pi'],
195       ['5.8*5.8*PI', '5.8 * 5.8 * %pi'],
196       ['3e * 5x^2', '3 * %e * 5 * x^2'],
197       ['3E * 5x^2', '3 * %e * 5 * x^2'],
198       ['3 + 2i', '3 + 2 * %i'],
199       ['(-24x + 37)(71x - 33)', '(-24 * x + 37) * (71 * x - 33)'],
200       ['x^((3y^2+5y)(y^2+2-x))', 'x^((3 * y^2 + 5 * y) * (y^2 + 2 - x))'],
201       ['-x^(-(-3y^2+-5y)(y^-2+2-x))', '-x^(-(-3 * y^2 + -5 * y) * (y^-2 + 2 - x))'],
202       ['(x^3 + 1)(x^2 + 2)(x + 1)', '(x^3 + 1) * (x^2 + 2) * (x + 1)'],
203       ['(x^3 + 1)(x^2 + 2)(x + 1)(y^2 - 11)', '(x^3 + 1) * (x^2 + 2) * (x + 1) * (y^2 - 11)'],
204       ['(x^3 + 1)(x^2 + 2)(x + 1)(y^2 - 11)(y^3 - 4)', '(x^3 + 1) * (x^2 + 2) * (x + 1) * (y^2 - 11) * (y^3 - 4)'],
205       ['a - 1', 'a - 1'],
206       ['6a^2 - a - 1', '6 * a^2 - a - 1'],
207       ['5 div 4', '5 div 4'],
208       ['5.0 div 4', '5.0 div 4'],
209       ['5/4', '5 / 4'],
210       ['5.0/4', '5.0 / 4'],
211       ['.04324134213', '0.043'],
212       ['- .04324134213', '-0.043'],
213       ['-50/12 div 12*32', '-50 / 12 div (12 * 32)'],
214       ['-sqrt(2)', '-sqrt(2)'],
215       ['-(5 - 2x)', '(2x - 5)'],
216       # TODO: need more pattern
217     ]
218   end
219
220   def self.bad_patterns
221     [
222       '1 + ', ' * 2', ' * ', '4 / 4 5',
223       '2(x^2 + xy + y^2',
224       'sqrt(2(x^2 + 3) + xyz^5 + y^2))',
225       'sqrt(2(x^(2 + ) + rot(xyz^5) + y^2))',
226       '5xc*1/5 + 1 (34 - 1 /8 + 1)* / 1',
227       # TODO: need more pattern
228     ]
229   end
230 end
231