pairwise 0.1.0 → 0.1.1
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.
- data/README.rdoc +13 -0
- data/VERSION.yml +1 -1
- data/features/generating_pairwise_data.feature +10 -10
- data/lib/pairwise/builder.rb +61 -58
- data/lib/pairwise/formatter/cucumber.rb +16 -7
- data/lib/pairwise/test_pair.rb +3 -3
- metadata +4 -2
data/README.rdoc
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
= Pairwise
|
2
|
+
|
3
|
+
Documentation is at http://github.com/josephwilk/pairwise/wikis/home/
|
4
|
+
|
5
|
+
== Running tests
|
6
|
+
|
7
|
+
rake
|
8
|
+
|
9
|
+
If you get errors about missing gems - just install them.
|
10
|
+
|
11
|
+
== Copyright
|
12
|
+
|
13
|
+
Copyright (c) 2009,2010 Joseph Wilk. See LICENSE for details.
|
data/VERSION.yml
CHANGED
@@ -66,15 +66,15 @@ Scenario: Not replacing wild cards
|
|
66
66
|
When I run pairwise inputs.yml --keep-wild-cards
|
67
67
|
Then I should see the output
|
68
68
|
"""
|
69
|
-
| A | B
|
70
|
-
| A1 | B1
|
71
|
-
| A1 | B2
|
72
|
-
| A2 | B1
|
73
|
-
| A2 | B2
|
74
|
-
| A3 | B1
|
75
|
-
| A3 | B2
|
76
|
-
| A3 |
|
77
|
-
| A2 |
|
78
|
-
| A1 |
|
69
|
+
| A | B | C |
|
70
|
+
| A1 | B1 | C1 |
|
71
|
+
| A1 | B2 | C2 |
|
72
|
+
| A2 | B1 | C3 |
|
73
|
+
| A2 | B2 | C1 |
|
74
|
+
| A3 | B1 | C2 |
|
75
|
+
| A3 | B2 | C3 |
|
76
|
+
| A3 | any_value_of_B | C1 |
|
77
|
+
| A2 | any_value_of_B | C2 |
|
78
|
+
| A1 | any_value_of_B | C3 |
|
79
79
|
|
80
80
|
"""
|
data/lib/pairwise/builder.rb
CHANGED
@@ -6,81 +6,84 @@ module Pairwise
|
|
6
6
|
WILD_CARD = 'wild_card'
|
7
7
|
|
8
8
|
def initialize(inputs, options = {})
|
9
|
-
@
|
9
|
+
@list_of_input_values = inputs
|
10
10
|
@options = options
|
11
11
|
end
|
12
12
|
|
13
13
|
def build
|
14
|
-
|
15
|
-
@
|
14
|
+
input_combinations = generate_pairs_between(@list_of_input_values[0], [@list_of_input_values[1]], 0)
|
15
|
+
@list_of_input_values.size > 2 ? in_parameter_order_generation(input_combinations) : input_combinations.map{|list| list.to_a}
|
16
16
|
end
|
17
17
|
|
18
18
|
private
|
19
19
|
|
20
|
-
def in_parameter_order_generation(
|
21
|
-
@
|
20
|
+
def in_parameter_order_generation(input_combinations)
|
21
|
+
@list_of_input_values[2..-1].each_with_index do |input_values, i|
|
22
22
|
i += 2
|
23
|
-
|
24
|
-
|
23
|
+
input_combinations, uncovered_pairs = horizontal_growth(input_combinations, input_values, @list_of_input_values[0..(i-1)])
|
24
|
+
input_combinations = vertical_growth(input_combinations, uncovered_pairs)
|
25
25
|
end
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
input_combinations = replace_redundant_wild_cards(input_combinations)
|
27
|
+
input_combinations = replace_wild_cards(input_combinations) unless @options[:keep_wild_cards]
|
28
|
+
input_combinations
|
29
29
|
end
|
30
30
|
|
31
|
-
def horizontal_growth(
|
32
|
-
|
31
|
+
def horizontal_growth(input_combinations, input_values_for_growth, previously_grown_input_values)
|
32
|
+
uncovered_pairs = generate_pairs_between(input_values_for_growth, previously_grown_input_values, previously_grown_input_values.size)
|
33
33
|
|
34
|
-
if
|
35
|
-
|
36
|
-
extended_input_list = input_list + [parameter_i[index_of_input_under_inspection]]
|
37
|
-
pi = remove_pairs_covered_by(extended_input_list, pi)
|
38
|
-
extended_input_list
|
39
|
-
end
|
34
|
+
if input_combinations.size <= input_values_for_growth.size
|
35
|
+
input_combinations, uncovered_pairs = grow_input_combinations_and_remove_covered_pairs(input_combinations, input_values_for_growth, uncovered_pairs)
|
40
36
|
else
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
pi = remove_pairs_covered_by(extended_input_list, pi)
|
50
|
-
extended_input_list
|
37
|
+
range_to_grow = 0...input_values_for_growth.size
|
38
|
+
input_combinations[range_to_grow], uncovered_pairs = grow_input_combinations_and_remove_covered_pairs(input_combinations[range_to_grow], input_values_for_growth, uncovered_pairs)
|
39
|
+
|
40
|
+
range_to_grow = input_values_for_growth.size..-1
|
41
|
+
input_combinations[range_to_grow] = input_combinations[range_to_grow].map do |input_combination|
|
42
|
+
extended_input_combination = input_combination_that_covers_most_pairs(input_combination, input_values_for_growth, uncovered_pairs)
|
43
|
+
uncovered_pairs = remove_pairs_covered_by(extended_input_combination, uncovered_pairs)
|
44
|
+
extended_input_combination
|
51
45
|
end
|
52
46
|
end
|
53
47
|
|
54
|
-
[
|
48
|
+
[input_combinations, uncovered_pairs]
|
55
49
|
end
|
56
50
|
|
57
|
-
def
|
58
|
-
|
51
|
+
def grow_input_combinations_and_remove_covered_pairs(input_combinations, input_values_for_growth, uncovered_pairs)
|
52
|
+
input_combinations = input_combinations.enum_for(:each_with_index).map do |input_combination, input_index|
|
53
|
+
extended_input_combination = input_combination + [input_values_for_growth[input_index]]
|
54
|
+
uncovered_pairs = remove_pairs_covered_by(extended_input_combination, uncovered_pairs)
|
55
|
+
extended_input_combination
|
56
|
+
end
|
57
|
+
[input_combinations, uncovered_pairs]
|
58
|
+
end
|
59
|
+
|
60
|
+
def vertical_growth(input_combinations, uncovered_pairs)
|
61
|
+
new_input_combinations = []
|
59
62
|
|
60
|
-
|
63
|
+
uncovered_pairs.each do |uncovered_pair|
|
61
64
|
#TODO: Decided if we should replace all matches or single matches?
|
62
|
-
if test_position = uncovered_pair.replaceable_wild_card?(
|
63
|
-
|
65
|
+
if test_position = uncovered_pair.replaceable_wild_card?(new_input_combinations)
|
66
|
+
new_input_combinations[test_position] = uncovered_pair.replace_wild_card(new_input_combinations[test_position])
|
64
67
|
else
|
65
|
-
|
68
|
+
new_input_combinations << uncovered_pair.create_input_list
|
66
69
|
end
|
67
70
|
end
|
68
71
|
|
69
|
-
|
72
|
+
input_combinations + new_input_combinations
|
70
73
|
end
|
71
74
|
|
72
|
-
def replace_redundant_wild_cards(
|
73
|
-
map_each_input_value(
|
74
|
-
if input_value == WILD_CARD && @
|
75
|
-
@
|
75
|
+
def replace_redundant_wild_cards(input_combinations)
|
76
|
+
map_each_input_value(input_combinations) do |input_value, index|
|
77
|
+
if input_value == WILD_CARD && @list_of_input_values[index].length == 1
|
78
|
+
@list_of_input_values[index][0]
|
76
79
|
else
|
77
80
|
input_value
|
78
81
|
end
|
79
82
|
end
|
80
83
|
end
|
81
84
|
|
82
|
-
def replace_wild_cards(
|
83
|
-
map_each_input_value(
|
85
|
+
def replace_wild_cards(input_combinations)
|
86
|
+
map_each_input_value(input_combinations) do |input_value, index|
|
84
87
|
if input_value == WILD_CARD
|
85
88
|
pick_random_value(@inputs[index])
|
86
89
|
else
|
@@ -89,16 +92,16 @@ module Pairwise
|
|
89
92
|
end
|
90
93
|
end
|
91
94
|
|
92
|
-
def map_each_input_value(
|
93
|
-
|
94
|
-
|
95
|
+
def map_each_input_value(input_combinations)
|
96
|
+
input_combinations.map do |input_combination|
|
97
|
+
input_combination.enum_for(:each_with_index).map do |input_value, index|
|
95
98
|
yield input_value, index
|
96
99
|
end
|
97
100
|
end
|
98
101
|
end
|
99
102
|
|
100
|
-
def pick_random_value(
|
101
|
-
|
103
|
+
def pick_random_value(input_combination)
|
104
|
+
input_combination[rand(input_combination.size)]
|
102
105
|
end
|
103
106
|
|
104
107
|
def generate_pairs_between(parameter_i, input_lists, p_index)
|
@@ -113,28 +116,28 @@ module Pairwise
|
|
113
116
|
pairs
|
114
117
|
end
|
115
118
|
|
116
|
-
def remove_pairs_covered_by(extended_input_list,
|
117
|
-
|
119
|
+
def remove_pairs_covered_by(extended_input_list, pairs)
|
120
|
+
pairs.reject{|pair| pair.covered_by?(extended_input_list)}
|
118
121
|
end
|
119
122
|
|
120
|
-
def
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
covered_count = pairs_covered_count(
|
123
|
+
def input_combination_that_covers_most_pairs(input_combination, input_values_for_growth, pairs)
|
124
|
+
selected_input_combination = nil
|
125
|
+
input_values_for_growth.reduce(0) do |max_covered_count, value|
|
126
|
+
input_combination_candidate = input_combination + [value]
|
127
|
+
covered_count = pairs_covered_count(input_combination_candidate, pairs)
|
125
128
|
if covered_count >= max_covered_count
|
126
|
-
|
129
|
+
selected_input_combination = input_combination_candidate
|
127
130
|
covered_count
|
128
131
|
else
|
129
132
|
max_covered_count
|
130
133
|
end
|
131
134
|
end
|
132
|
-
|
135
|
+
selected_input_combination
|
133
136
|
end
|
134
137
|
|
135
|
-
def pairs_covered_count(
|
138
|
+
def pairs_covered_count(input_combination, pairs)
|
136
139
|
pairs.reduce(0) do |covered_count, pair|
|
137
|
-
covered_count += 1 if pair.covered_by?(
|
140
|
+
covered_count += 1 if pair.covered_by?(input_combination)
|
138
141
|
covered_count
|
139
142
|
end
|
140
143
|
end
|
@@ -7,16 +7,17 @@ module Pairwise
|
|
7
7
|
@max = {}
|
8
8
|
end
|
9
9
|
|
10
|
-
def display(test_data,
|
11
|
-
@test_data
|
12
|
-
|
10
|
+
def display(test_data, input_labels)
|
11
|
+
@test_data = label_wild_cards(test_data, input_labels)
|
12
|
+
@input_labels = input_labels
|
13
|
+
|
13
14
|
@out.print "|"
|
14
|
-
|
15
|
-
@out.print padded_string(
|
15
|
+
@input_labels.each_with_index do |label, column|
|
16
|
+
@out.print padded_string(label, column) + "|"
|
16
17
|
end
|
17
18
|
@out.puts
|
18
19
|
|
19
|
-
test_data.each do |data|
|
20
|
+
@test_data.each do |data|
|
20
21
|
@out.print "|"
|
21
22
|
data.each_with_index do |datum, column|
|
22
23
|
@out.print padded_string(datum, column) + "|"
|
@@ -26,13 +27,21 @@ module Pairwise
|
|
26
27
|
end
|
27
28
|
|
28
29
|
private
|
30
|
+
def label_wild_cards(test_data, labels)
|
31
|
+
test_data.map do |data|
|
32
|
+
data.enum_for(:each_with_index).map do |datum, column|
|
33
|
+
datum == Builder::WILD_CARD ? "any_value_of_#{labels[column]}" : datum
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
29
38
|
def padded_string(string, column)
|
30
39
|
padding_length = max_line_length(column) - string.length
|
31
40
|
" #{string} " + (" " * padding_length)
|
32
41
|
end
|
33
42
|
|
34
43
|
def max_line_length(column)
|
35
|
-
@max[column] ||= ([@
|
44
|
+
@max[column] ||= ([@input_labels[column].length] + @test_data.map{|data| data[column].length}).max
|
36
45
|
end
|
37
46
|
|
38
47
|
end
|
data/lib/pairwise/test_pair.rb
CHANGED
@@ -30,9 +30,9 @@ module Pairwise
|
|
30
30
|
input_list
|
31
31
|
end
|
32
32
|
|
33
|
-
def replaceable_wild_card?(
|
34
|
-
wild_card_list =
|
35
|
-
|
33
|
+
def replaceable_wild_card?(input_combinations)
|
34
|
+
wild_card_list = input_combinations.map do |input_combination|
|
35
|
+
input_combination[@p2_position] == Builder::WILD_CARD && input_combination[@p1_position] == @p1
|
36
36
|
end
|
37
37
|
wild_card_list.rindex(true)
|
38
38
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pairwise
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joseph Wilk
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-07 00:00:00 +00:00
|
13
13
|
default_executable: pairwise
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -40,9 +40,11 @@ extensions: []
|
|
40
40
|
|
41
41
|
extra_rdoc_files:
|
42
42
|
- LICENSE
|
43
|
+
- README.rdoc
|
43
44
|
files:
|
44
45
|
- .gitignore
|
45
46
|
- LICENSE
|
47
|
+
- README.rdoc
|
46
48
|
- Rakefile
|
47
49
|
- VERSION.yml
|
48
50
|
- bin/pairwise
|