test_case_generator 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/test_case_generator/cli.rb +2 -0
- data/lib/test_case_generator/dsl_context.rb +65 -0
- data/lib/test_case_generator/generator_cplusplus.rb +86 -0
- data/lib/test_case_generator/generator_java.rb +39 -13
- data/lib/test_case_generator/generator_php.rb +40 -4
- data/lib/test_case_generator/generator_python.rb +43 -5
- data/lib/test_case_generator/state_machine.rb +128 -0
- data/lib/test_case_generator/utils.rb +53 -0
- data/lib/test_case_generator/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eaf8f594bdd3875c4f28d422053be70b8bb833ff
|
4
|
+
data.tar.gz: 97b3477ddd6a9128074a316f8679cf1071ee2d4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 878c20c974e98c99b8836af666db046618e4220bdf9e670b5c97fc436c7aab409712b32c6c793c069fb93be3acc58ad480faa5f04891b2e348b5dc73a2f258e6
|
7
|
+
data.tar.gz: 64475acb5c35699342caf6126f71e833b11b2c45ac7d15225bbc044ddab2e6f95ad9a1dfb97724b8afc8aa0d110d1b19778e51e255cffe28d58f66a05df07602
|
@@ -8,6 +8,7 @@ require 'test_case_generator/generator_java'
|
|
8
8
|
require 'test_case_generator/generator_php'
|
9
9
|
require 'test_case_generator/generator_python'
|
10
10
|
require 'test_case_generator/generator_javascript'
|
11
|
+
require 'test_case_generator/generator_cplusplus'
|
11
12
|
|
12
13
|
module TestCaseGenerator
|
13
14
|
class CLI < Thor
|
@@ -24,6 +25,7 @@ module TestCaseGenerator
|
|
24
25
|
factory.register TestCaseGenerator::GeneratorPHP.new
|
25
26
|
factory.register TestCaseGenerator::GeneratorPython.new
|
26
27
|
factory.register TestCaseGenerator::GeneratorJavaScript.new
|
28
|
+
factory.register TestCaseGenerator::GeneratorCplusplus.new
|
27
29
|
|
28
30
|
gen = factory.query source_fn
|
29
31
|
gen.write ctx, source_fn
|
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'test_case_generator/utils'
|
2
|
+
require 'test_case_generator/state_machine'
|
2
3
|
|
3
4
|
module TestCaseGenerator
|
4
5
|
class DSLContext
|
5
6
|
attr_reader :children
|
6
7
|
attr_reader :labels
|
8
|
+
attr_reader :class_name
|
7
9
|
|
8
10
|
def initialize
|
9
11
|
@patterns = []
|
@@ -11,6 +13,7 @@ module TestCaseGenerator
|
|
11
13
|
@after = []
|
12
14
|
@children = []
|
13
15
|
@labels = []
|
16
|
+
@class_name = nil
|
14
17
|
end
|
15
18
|
|
16
19
|
def <<(events)
|
@@ -127,6 +130,68 @@ module TestCaseGenerator
|
|
127
130
|
end
|
128
131
|
alias_method :para, :parallel
|
129
132
|
|
133
|
+
def def_state_machine(options={}, &block)
|
134
|
+
ctx = StateMachineContext.new(options)
|
135
|
+
ctx.instance_eval &block if block_given?
|
136
|
+
ctx
|
137
|
+
end
|
138
|
+
|
139
|
+
def state_machine(options={}, &block)
|
140
|
+
ctx = def_state_machine options, &block
|
141
|
+
|
142
|
+
ctx.items.each do |x|
|
143
|
+
@patterns << x
|
144
|
+
x.each do |label|
|
145
|
+
@labels << label unless @labels.include? label
|
146
|
+
end
|
147
|
+
end
|
148
|
+
# @patterns.concat ctx.items
|
149
|
+
end
|
150
|
+
|
151
|
+
def add_async_events(src_items, options={})
|
152
|
+
out_items = []
|
153
|
+
|
154
|
+
src_items.each do |pattern1|
|
155
|
+
idx_from = options[:from].nil? ? nil : pattern1.find_index{|item| item==options[:from]}
|
156
|
+
if idx_from.nil?
|
157
|
+
out_items << pattern1
|
158
|
+
next
|
159
|
+
end
|
160
|
+
|
161
|
+
pattern2 = pattern1[idx_from + 1 ... pattern1.size]
|
162
|
+
idx_to = options[:to].nil? ? nil : pattern2.find_index{|item| item==options[:to]}
|
163
|
+
|
164
|
+
tmp_items = idx_to.nil? ? [pattern2] : [pattern2[0 ... idx_to]]
|
165
|
+
Utils.para! tmp_items, options[:items]
|
166
|
+
|
167
|
+
out_items.concat tmp_items.map{ |ptn| pattern1[0 .. idx_from] + ptn + (idx_to.nil? ? [] : pattern2[idx_to ... pattern2.size]) }
|
168
|
+
end
|
169
|
+
|
170
|
+
out_items.uniq
|
171
|
+
end
|
172
|
+
|
173
|
+
def add_async_events!(src_items, options={})
|
174
|
+
tmp_items = add_async_events(src_items, options)
|
175
|
+
|
176
|
+
src_items.clear
|
177
|
+
src_items.concat tmp_items
|
178
|
+
src_items
|
179
|
+
end
|
180
|
+
|
181
|
+
def add_patterns(patterns)
|
182
|
+
@patterns.concat patterns
|
183
|
+
|
184
|
+
patterns.each do |pattern|
|
185
|
+
pattern.each do |label|
|
186
|
+
@labels << label unless @labels.include? label
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def set_class_name(class_name)
|
192
|
+
@class_name = class_name
|
193
|
+
end
|
194
|
+
|
130
195
|
def raw_each
|
131
196
|
@patterns.each { |ptn| yield @before + ptn + @after }
|
132
197
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'test_case_generator/dsl_context'
|
2
|
+
require 'test_case_generator/indented_writer'
|
3
|
+
|
4
|
+
module TestCaseGenerator
|
5
|
+
class GeneratorCplusplus
|
6
|
+
def can_handle?(source_fn)
|
7
|
+
File.extname(source_fn).eql? '.cpp'
|
8
|
+
end
|
9
|
+
|
10
|
+
def write(ctx, source_fn)
|
11
|
+
write_skeleton source_fn unless File.exist? source_fn
|
12
|
+
write_source ctx, source_fn
|
13
|
+
end
|
14
|
+
|
15
|
+
def make_class_name(filename)
|
16
|
+
File.basename filename, '.*'
|
17
|
+
end
|
18
|
+
|
19
|
+
def write_skeleton(source_fn)
|
20
|
+
class_name = make_class_name(source_fn)
|
21
|
+
File.open(source_fn, 'w') do |f|
|
22
|
+
writer = IndentedWriter.new f
|
23
|
+
writer.puts <<EOS
|
24
|
+
#include <gtest/gtest.h>
|
25
|
+
|
26
|
+
class #{class_name} : public testing::Test
|
27
|
+
{
|
28
|
+
protected:
|
29
|
+
// TODO: Declares the variables your tests want to use.
|
30
|
+
|
31
|
+
protected:
|
32
|
+
virtual void SetUp() {
|
33
|
+
}
|
34
|
+
|
35
|
+
virtual void TearDown() {
|
36
|
+
}
|
37
|
+
|
38
|
+
protected:
|
39
|
+
// TODO: ここにアクションを書いてください
|
40
|
+
};
|
41
|
+
|
42
|
+
// %%
|
43
|
+
EOS
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def write_source(dsl_context, source_fn)
|
48
|
+
class_name = make_class_name(source_fn)
|
49
|
+
tmp_fn = source_fn + '.tmp'
|
50
|
+
source = File.open(source_fn).read
|
51
|
+
File.open(tmp_fn, 'w') do |f|
|
52
|
+
source.each_line do |line|
|
53
|
+
f.puts line
|
54
|
+
break if line =~ /^\s*\/\/\s*%%\s*$/
|
55
|
+
end
|
56
|
+
|
57
|
+
writer = IndentedWriter.new f
|
58
|
+
writer.blank
|
59
|
+
writer.puts '//'
|
60
|
+
writer.puts '// 以下の行は自動生成されているので直接編集しないでください。'
|
61
|
+
writer.puts '//'
|
62
|
+
writer.puts '// Generated by Test Case Generator'
|
63
|
+
writer.puts '// https://rubygems.org/gems/test_case_generator'
|
64
|
+
writer.puts '//'
|
65
|
+
|
66
|
+
dsl_context.each do |pattern|
|
67
|
+
method_name = pattern.join '_'
|
68
|
+
writer.blank
|
69
|
+
writer.puts "TEST_F(#{class_name}, #{method_name}) {"
|
70
|
+
|
71
|
+
pattern.each do |ptn|
|
72
|
+
writer.block_indent ' ' do
|
73
|
+
writer.puts "#{ptn}();"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
writer.puts '}'
|
78
|
+
end
|
79
|
+
|
80
|
+
# writer.blank
|
81
|
+
end
|
82
|
+
|
83
|
+
FileUtils.move tmp_fn, source_fn
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -9,7 +9,7 @@ module TestCaseGenerator
|
|
9
9
|
|
10
10
|
def write(ctx, source_fn)
|
11
11
|
write_skeleton source_fn unless File.exist? source_fn
|
12
|
-
write_interface ctx, File.join(File.dirname(source_fn), make_interface_name(source_fn)) + '.java'
|
12
|
+
write_interface ctx, File.join(File.dirname(source_fn), make_interface_name(source_fn)) + '.java', make_package_name(source_fn)
|
13
13
|
write_source ctx, source_fn
|
14
14
|
end
|
15
15
|
|
@@ -51,21 +51,46 @@ import org.junit.Before;
|
|
51
51
|
import org.junit.Test;
|
52
52
|
import org.junit.runner.RunWith;
|
53
53
|
import org.robolectric.Robolectric;
|
54
|
+
import org.robolectric.RobolectricGradleTestRunner;
|
54
55
|
import org.robolectric.RobolectricTestRunner;
|
55
56
|
import org.robolectric.annotation.Config;
|
56
57
|
|
58
|
+
import java.util.ArrayList;
|
59
|
+
|
57
60
|
import static org.junit.Assert.*;
|
58
61
|
|
59
|
-
@RunWith(
|
60
|
-
@Config(
|
62
|
+
@RunWith(RobolectricGradleTestRunner.class)
|
63
|
+
@Config(constants = BuildConfig.class, sdk = 18)
|
61
64
|
public class #{class_name} implements #{make_interface_name source_fn} {
|
62
65
|
|
63
66
|
@Before
|
64
67
|
public void setUp() {
|
68
|
+
Robolectric.getForegroundThreadScheduler().reset();
|
69
|
+
Robolectric.getForegroundThreadScheduler().pause();
|
70
|
+
Robolectric.getBackgroundThreadScheduler().reset();
|
71
|
+
Robolectric.getBackgroundThreadScheduler().pause();
|
65
72
|
}
|
66
73
|
|
67
74
|
@After
|
68
75
|
public void tearDown() {
|
76
|
+
Robolectric.getForegroundThreadScheduler().reset();
|
77
|
+
Robolectric.getForegroundThreadScheduler().unPause();
|
78
|
+
Robolectric.getBackgroundThreadScheduler().reset();
|
79
|
+
Robolectric.getBackgroundThreadScheduler().unPause();
|
80
|
+
}
|
81
|
+
|
82
|
+
// TODO: Please implement custom actions here.
|
83
|
+
|
84
|
+
private void printPatterns(String patterns) {
|
85
|
+
System.err.println("<<TEST>> " + patterns);
|
86
|
+
}
|
87
|
+
|
88
|
+
private void runPendingTasks() {
|
89
|
+
Robolectric.getForegroundThreadScheduler().advanceBy(1);
|
90
|
+
}
|
91
|
+
|
92
|
+
private void runTimerTasks() {
|
93
|
+
Robolectric.getForegroundThreadScheduler().advanceBy(30 * 1000);
|
69
94
|
}
|
70
95
|
|
71
96
|
// %%
|
@@ -74,17 +99,16 @@ EOS
|
|
74
99
|
end
|
75
100
|
end
|
76
101
|
|
77
|
-
def write_interface(dsl_context, header_fn)
|
102
|
+
def write_interface(dsl_context, header_fn, package_name)
|
78
103
|
interface_name = File.basename(header_fn, File.extname(header_fn))
|
79
104
|
tmp_fn = header_fn + '.tmp'
|
80
105
|
File.open(tmp_fn, 'w') do |f|
|
81
106
|
writer = IndentedWriter.new f
|
107
|
+
writer.puts <<EOS
|
108
|
+
package #{package_name};
|
82
109
|
|
83
|
-
|
84
|
-
|
85
|
-
writer.blank
|
86
|
-
writer.puts "public interface #{interface_name} {"
|
87
|
-
|
110
|
+
public interface #{interface_name} {
|
111
|
+
EOS
|
88
112
|
writer.block_indent ' ' do
|
89
113
|
dsl_context.labels.each do |label|
|
90
114
|
method_name = label
|
@@ -92,7 +116,9 @@ EOS
|
|
92
116
|
end
|
93
117
|
end
|
94
118
|
|
95
|
-
writer.puts
|
119
|
+
writer.puts <<EOS
|
120
|
+
}
|
121
|
+
EOS
|
96
122
|
end
|
97
123
|
|
98
124
|
FileUtils.move tmp_fn, header_fn
|
@@ -124,9 +150,9 @@ EOS
|
|
124
150
|
writer.blank
|
125
151
|
writer.puts '@Test'
|
126
152
|
writer.puts "public void test_#{method_name}() {"
|
127
|
-
|
128
|
-
|
129
|
-
|
153
|
+
writer.block_indent ' ' do
|
154
|
+
writer.puts "printPatterns(\"#{pattern.map{|p| "#{p}"}.join(', ')}\");"
|
155
|
+
pattern.each do |ptn|
|
130
156
|
writer.puts "#{ptn}();"
|
131
157
|
end
|
132
158
|
end
|
@@ -8,18 +8,45 @@ module TestCaseGenerator
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def write(ctx, source_fn)
|
11
|
-
|
11
|
+
write_skeleton source_fn unless File.exist? source_fn
|
12
|
+
write_interface ctx, File.join(File.dirname(source_fn), File.basename(source_fn, File.extname(source_fn)) + 'Generated.php')
|
12
13
|
write_source ctx, source_fn
|
13
14
|
end
|
14
15
|
|
15
|
-
def
|
16
|
-
|
16
|
+
def make_class_name(filename)
|
17
|
+
# File.join(File.dirname(source_fn), File.basename(source_fn, File.extname(source_fn))
|
18
|
+
File.basename filename, '.*'
|
19
|
+
end
|
20
|
+
|
21
|
+
def make_interface_name(filename)
|
22
|
+
make_class_name(filename) + 'Generated'
|
23
|
+
end
|
24
|
+
|
25
|
+
def write_skeleton(source_fn)
|
26
|
+
class_name = make_class_name(source_fn)
|
27
|
+
File.open(source_fn, 'w') do |f|
|
28
|
+
writer = IndentedWriter.new f
|
29
|
+
writer.puts <<EOS
|
30
|
+
<?php
|
31
|
+
require_once '#{make_interface_name source_fn}.php';
|
32
|
+
|
33
|
+
class #{class_name} extends PHPUnit_Framework_TestCase implements #{make_interface_name source_fn}
|
34
|
+
{
|
35
|
+
// %%
|
36
|
+
}
|
37
|
+
EOS
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def write_interface(dsl_context, header_fn)
|
42
|
+
interface_name = File.basename(header_fn, File.extname(header_fn))
|
17
43
|
tmp_fn = header_fn + '.tmp'
|
18
44
|
File.open(tmp_fn, 'w') do |f|
|
19
45
|
writer = IndentedWriter.new f
|
20
46
|
|
47
|
+
writer.puts '<?php'
|
21
48
|
writer.blank
|
22
|
-
writer.puts "interface #{
|
49
|
+
writer.puts "interface #{interface_name} {"
|
23
50
|
|
24
51
|
writer.block_indent ' ' do
|
25
52
|
dsl_context.labels.each do |label|
|
@@ -44,6 +71,15 @@ module TestCaseGenerator
|
|
44
71
|
end
|
45
72
|
|
46
73
|
writer = IndentedWriter.new f
|
74
|
+
writer.blank
|
75
|
+
writer.block_indent ' ' do
|
76
|
+
writer.puts '//'
|
77
|
+
writer.puts '// 以下の行は自動生成されているので直接編集しないでください。'
|
78
|
+
writer.puts '//'
|
79
|
+
writer.puts '// Generated by Test Case Generator'
|
80
|
+
writer.puts '// https://rubygems.org/gems/test_case_generator'
|
81
|
+
writer.puts '//'
|
82
|
+
end
|
47
83
|
|
48
84
|
dsl_context.each do |pattern|
|
49
85
|
method_name = pattern.join '_'
|
@@ -8,7 +8,7 @@ module TestCaseGenerator
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def write(ctx, source_fn)
|
11
|
-
write_skeleton source_fn unless File.exist? source_fn
|
11
|
+
write_skeleton ctx, source_fn unless File.exist? source_fn
|
12
12
|
write_source ctx, source_fn
|
13
13
|
end
|
14
14
|
|
@@ -16,8 +16,8 @@ module TestCaseGenerator
|
|
16
16
|
File.basename filename, '.*'
|
17
17
|
end
|
18
18
|
|
19
|
-
def write_skeleton(source_fn)
|
20
|
-
class_name = make_class_name(source_fn)
|
19
|
+
def write_skeleton(dsl_context, source_fn)
|
20
|
+
class_name = dsl_context.class_name || make_class_name(source_fn)
|
21
21
|
File.open(source_fn, 'w') do |f|
|
22
22
|
writer = IndentedWriter.new f
|
23
23
|
writer.puts <<EOS
|
@@ -26,22 +26,59 @@ module TestCaseGenerator
|
|
26
26
|
import os
|
27
27
|
import sys
|
28
28
|
import unittest
|
29
|
+
# from assets.stub_android import stub_api_model
|
30
|
+
# from assets.stub_android import stub_android
|
31
|
+
|
32
|
+
|
33
|
+
def print_patterns(patterns):
|
34
|
+
def wrapper(fn):
|
35
|
+
def _(self):
|
36
|
+
print
|
37
|
+
print "<<TEST>> %s" % (", ".join(patterns))
|
38
|
+
fn(self)
|
39
|
+
return _
|
40
|
+
return wrapper
|
41
|
+
|
42
|
+
|
43
|
+
def run_pending_tasks(fn):
|
44
|
+
def _(self):
|
45
|
+
fn(self)
|
46
|
+
|
47
|
+
while len(self.pending_tasks) > 0:
|
48
|
+
# http://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list-in-python
|
49
|
+
# Use instead of a weird syntax new_list = old_list[:]
|
50
|
+
pending_tasks = list(self.pending_tasks)
|
51
|
+
self.pending_tasks[:] = []
|
52
|
+
|
53
|
+
for task in pending_tasks:
|
54
|
+
task() # Maybe added into self.pending_tasks
|
55
|
+
|
56
|
+
return _
|
29
57
|
|
30
58
|
|
31
59
|
class #{class_name}(unittest.TestCase):
|
32
60
|
def setUp(self):
|
33
61
|
super(#{class_name}, self).setUp()
|
62
|
+
self.pending_tasks = []
|
63
|
+
self.timer_tasks = []
|
34
64
|
|
35
65
|
def tearDown(self):
|
36
66
|
super(#{class_name}, self).tearDown()
|
37
67
|
|
38
|
-
|
68
|
+
def _run_timer_tasks(self):
|
69
|
+
timer_tasks = list(self.timer_tasks)
|
70
|
+
self.timer_tasks[:] = []
|
71
|
+
|
72
|
+
for task in timer_tasks:
|
73
|
+
task() # Maybe added into self.timer_tasks
|
74
|
+
|
75
|
+
# %%
|
39
76
|
EOS
|
40
77
|
end
|
41
78
|
end
|
42
79
|
|
43
80
|
def write_source(dsl_context, source_fn)
|
44
|
-
class_name = make_class_name(source_fn)
|
81
|
+
class_name = dsl_context.class_name || make_class_name(source_fn)
|
45
82
|
tmp_fn = source_fn + '.tmp'
|
46
83
|
source = File.open(source_fn).read
|
47
84
|
File.open(tmp_fn, 'w') do |f|
|
@@ -65,6 +102,7 @@ EOS
|
|
65
102
|
method_name = pattern.join '_'
|
66
103
|
writer.block_indent ' ' do
|
67
104
|
writer.blank
|
105
|
+
writer.puts "@print_patterns([#{pattern.map{|p| "'#{p}'"}.join(', ')}])"
|
68
106
|
writer.puts "def test_#{method_name}(self):"
|
69
107
|
|
70
108
|
pattern.each do |ptn|
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'test_case_generator/utils'
|
2
|
+
|
3
|
+
module TestCaseGenerator
|
4
|
+
class Path
|
5
|
+
attr_reader :src_state, :dest_state
|
6
|
+
|
7
|
+
def initialize(src_state, dest_state, attrs={})
|
8
|
+
@src_state = src_state
|
9
|
+
@dest_state = dest_state
|
10
|
+
@attrs = attrs
|
11
|
+
end
|
12
|
+
|
13
|
+
def items
|
14
|
+
@attrs[:items] || []
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class State
|
19
|
+
attr_reader :name
|
20
|
+
|
21
|
+
def initialize(name, attrs={})
|
22
|
+
@name = name
|
23
|
+
@attrs = attrs
|
24
|
+
end
|
25
|
+
|
26
|
+
def items
|
27
|
+
@attrs[:items] || []
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Fork
|
32
|
+
attr_reader :state
|
33
|
+
|
34
|
+
def initialize(state, attrs={})
|
35
|
+
@state = state
|
36
|
+
@attrs = attrs
|
37
|
+
end
|
38
|
+
|
39
|
+
def items
|
40
|
+
@attrs[:items] || []
|
41
|
+
end
|
42
|
+
|
43
|
+
# def join
|
44
|
+
# @attrs[:join]
|
45
|
+
# end
|
46
|
+
end
|
47
|
+
|
48
|
+
class StateMachineContext
|
49
|
+
def initialize(attrs={})
|
50
|
+
@attrs = attrs
|
51
|
+
|
52
|
+
@state_list = []
|
53
|
+
@path_list = []
|
54
|
+
@fork_list = []
|
55
|
+
@start_state = attrs[:start_state]
|
56
|
+
@reject_block = nil
|
57
|
+
@filter_block = nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_state(name, options={})
|
61
|
+
ctx = State.new(name, options)
|
62
|
+
@state_list << ctx
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_path(src_state, dest_state, options={})
|
66
|
+
ctx = Path.new(src_state, dest_state, options)
|
67
|
+
@path_list << ctx
|
68
|
+
end
|
69
|
+
|
70
|
+
def reject(&block)
|
71
|
+
@reject_block = block
|
72
|
+
end
|
73
|
+
|
74
|
+
def filter(&block)
|
75
|
+
@filter_block = block
|
76
|
+
end
|
77
|
+
|
78
|
+
def fork(state, options={})
|
79
|
+
@fork_list << Fork.new(state, options)
|
80
|
+
end
|
81
|
+
|
82
|
+
def start_state
|
83
|
+
if @start_state.nil?
|
84
|
+
@state_list[0]
|
85
|
+
else
|
86
|
+
@state_list.find{ |state| state.name == @start_state }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def items(options={})
|
91
|
+
out_items = []
|
92
|
+
counter = {}
|
93
|
+
_items! out_items, counter, start_state, options
|
94
|
+
out_items.uniq!
|
95
|
+
out_items.reject! &(@reject_block) unless @reject_block.nil?
|
96
|
+
out_items.keep_if &(@filter_block) unless @filter_block.nil?
|
97
|
+
|
98
|
+
p out_items
|
99
|
+
out_items
|
100
|
+
end
|
101
|
+
|
102
|
+
def _items!(out_items, counter, state, options={})
|
103
|
+
return if state.nil?
|
104
|
+
|
105
|
+
count = counter[state.name] || 0
|
106
|
+
count += 1
|
107
|
+
counter[state.name] = count
|
108
|
+
|
109
|
+
return if count > (options[:limit] || 2)
|
110
|
+
|
111
|
+
Utils.concat! out_items, state.items
|
112
|
+
|
113
|
+
tmp_list0 = []
|
114
|
+
@path_list.find_all{|path| path.src_state == state.name}.each do |path|
|
115
|
+
tmp_list = []
|
116
|
+
Utils.concat! tmp_list, path.items
|
117
|
+
_items! tmp_list, counter.clone, @state_list.find{ |s| s.name == path.dest_state}
|
118
|
+
tmp_list0.concat tmp_list
|
119
|
+
end
|
120
|
+
|
121
|
+
@fork_list.find_all{|fork| fork.state == state.name}.each do |fork|
|
122
|
+
Utils.para! tmp_list0, fork.items
|
123
|
+
end
|
124
|
+
|
125
|
+
Utils.concat! out_items, tmp_list0
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -5,5 +5,58 @@ module TestCaseGenerator
|
|
5
5
|
buffer << (buffer.empty? ? e : e.capitalize)
|
6
6
|
end.join
|
7
7
|
end
|
8
|
+
|
9
|
+
def self.concat!(out_items, other_list)
|
10
|
+
if out_items.size == 0
|
11
|
+
out_items.concat other_list
|
12
|
+
else
|
13
|
+
return out_items if other_list.empty?
|
14
|
+
|
15
|
+
tmp_list = []
|
16
|
+
out_items.each do |item1|
|
17
|
+
other_list.each do |item2|
|
18
|
+
tmp_list << item1 + item2
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
out_items.clear
|
23
|
+
out_items.concat tmp_list
|
24
|
+
end
|
25
|
+
|
26
|
+
out_items
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.para!(out_items, other_list)
|
30
|
+
if out_items.size == 0
|
31
|
+
out_items.concat other_list
|
32
|
+
else
|
33
|
+
return out_items if other_list.empty?
|
34
|
+
tmp_list = []
|
35
|
+
out_items.each do |item1|
|
36
|
+
other_list.each do |item2|
|
37
|
+
(0...(item1.size + item2.size)).to_a.combination(item1.size) do |index_arr|
|
38
|
+
idx_item1 = 0
|
39
|
+
idx_item2 = 0
|
40
|
+
tmp_list << (0...(item1.size + item2.size)).to_a.map do |x|
|
41
|
+
if index_arr.include?(x)
|
42
|
+
picked = item1[idx_item1]
|
43
|
+
idx_item1 += 1
|
44
|
+
else
|
45
|
+
picked = item2[idx_item2]
|
46
|
+
idx_item2 += 1
|
47
|
+
end
|
48
|
+
|
49
|
+
picked
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
out_items.clear
|
56
|
+
out_items.concat tmp_list
|
57
|
+
end
|
58
|
+
|
59
|
+
out_items
|
60
|
+
end
|
8
61
|
end
|
9
62
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: test_case_generator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kaoru Yanase
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -104,6 +104,7 @@ files:
|
|
104
104
|
- lib/test_case_generator.rb
|
105
105
|
- lib/test_case_generator/cli.rb
|
106
106
|
- lib/test_case_generator/dsl_context.rb
|
107
|
+
- lib/test_case_generator/generator_cplusplus.rb
|
107
108
|
- lib/test_case_generator/generator_factory.rb
|
108
109
|
- lib/test_case_generator/generator_java.rb
|
109
110
|
- lib/test_case_generator/generator_javascript.rb
|
@@ -111,6 +112,7 @@ files:
|
|
111
112
|
- lib/test_case_generator/generator_php.rb
|
112
113
|
- lib/test_case_generator/generator_python.rb
|
113
114
|
- lib/test_case_generator/indented_writer.rb
|
115
|
+
- lib/test_case_generator/state_machine.rb
|
114
116
|
- lib/test_case_generator/utils.rb
|
115
117
|
- lib/test_case_generator/version.rb
|
116
118
|
- test_case_generator.gemspec
|