@@ -37,7 +37,7 @@ public function __construct()
37
37
public function getTestsGroupedBySize ($ suiteConfiguration , $ testNameToSize , $ time )
38
38
{
39
39
// we must have the lines argument in order to create the test groups
40
- if ($ time === 0 ) {
40
+ if ($ time == 0 ) {
41
41
throw new FastFailException (
42
42
"Please provide the argument '--time' to the robo command in order to " .
43
43
" generate grouped tests manifests for a parallel execution "
@@ -86,27 +86,38 @@ public function getTestsGroupedBySize($suiteConfiguration, $testNameToSize, $tim
86
86
*/
87
87
public function getTestsGroupedByFixedGroupCount ($ suiteConfiguration , $ testNameToSize , $ groupTotal )
88
88
{
89
- $ suiteNameToTestSize = $ this ->getSuiteNameToTestSize ($ suiteConfiguration );
90
-
91
- $ minRequiredGroupCount = count ($ suiteNameToTestSize );
92
- if (!empty ($ testNameToSize )) {
93
- $ minRequiredGroupCount += 1 ;
94
- }
95
- if ($ groupTotal < $ minRequiredGroupCount ) {
96
- throw new FastFailException (
97
- "Invalid parameter 'groupTotal': must be equal or greater than {$ minRequiredGroupCount }"
98
- );
99
- }
100
-
101
89
if (empty ($ suiteConfiguration )) {
102
90
return $ this ->convertArrayIndexStartingAtOne ($ this ->splitTestsIntoGroups ($ testNameToSize , $ groupTotal ));
103
91
}
104
92
93
+ $ suiteNameToTestSize = $ this ->getSuiteNameToTestSize ($ suiteConfiguration );
94
+
105
95
// Calculate suite group totals
106
96
$ suiteNameToGroupCount = $ this ->getSuiteGroupCounts ($ suiteNameToTestSize , $ testNameToSize , $ groupTotal );
107
97
108
- // Calculate test group total
109
- $ testGroupTotal = $ groupTotal - array_sum ($ suiteNameToGroupCount );
98
+ $ suitesGroupTotal = array_sum ($ suiteNameToGroupCount );
99
+
100
+ // Calculate minimum required groups
101
+ $ minSuiteGroupTotal = count ($ suiteNameToTestSize );
102
+ $ minTestGroupTotal = empty ($ testNameToSize ) ? 0 : 1 ;
103
+ $ minRequiredGroupTotal = $ minSuiteGroupTotal + $ minTestGroupTotal ;
104
+
105
+ if ($ groupTotal < $ minRequiredGroupTotal ) {
106
+ throw new FastFailException (
107
+ "Invalid parameter 'groupTotal': must be equal or greater than {$ minRequiredGroupTotal }"
108
+ );
109
+ } elseif ($ groupTotal < $ suitesGroupTotal + $ minTestGroupTotal ) {
110
+ // Split in savvy mode when $groupTotal requested is very small
111
+ $ testGroupTotal = $ minTestGroupTotal ;
112
+ // Reduce suite group total
113
+ $ suiteNameToGroupCount = $ this ->reduceSuiteGroupTotal (
114
+ $ suiteNameToGroupCount ,
115
+ $ groupTotal - $ minTestGroupTotal
116
+ );
117
+ } else {
118
+ // Calculate test group total
119
+ $ testGroupTotal = $ groupTotal - $ suitesGroupTotal ;
120
+ }
110
121
111
122
// Split tests and suites
112
123
$ testGroups = $ this ->splitTestsIntoGroups ($ testNameToSize , $ testGroupTotal );
@@ -140,19 +151,19 @@ private function getSuiteGroupCounts($suiteNameToTestSize, $testNameToSize, $gro
140
151
$ maxSuiteTime = max ($ suiteNameToSize );
141
152
142
153
// Calculate 2 possible suite group times
143
- $ ceilSuiteGroupNumber = ceil ($ maxSuiteTime / $ minGroupTime );
154
+ $ ceilSuiteGroupNumber = ( int ) ceil ($ maxSuiteTime / $ minGroupTime );
144
155
$ ceilSuiteGroupTime = max (ceil ($ maxSuiteTime / $ ceilSuiteGroupNumber ), $ minGroupTime );
145
- $ floorSuiteGroupNumber = floor ($ maxSuiteTime / $ minGroupTime );
146
- if ($ floorSuiteGroupNumber !== 0 ) {
156
+ $ floorSuiteGroupNumber = ( int ) floor ($ maxSuiteTime / $ minGroupTime );
157
+ if ($ floorSuiteGroupNumber != 0 ) {
147
158
$ floorSuiteGroupTime = max (ceil ($ maxSuiteTime / $ floorSuiteGroupNumber ), $ minGroupTime );
148
159
}
149
160
150
161
// Calculate test group time for ceiling
151
162
$ ceilSuiteNameToGroupCount = $ this ->getSuiteGroupCountFromGroupTime ($ suiteNameToTestSize , $ ceilSuiteGroupTime );
152
163
$ ceilSuiteGroupTotal = array_sum ($ ceilSuiteNameToGroupCount );
153
- $ ceilTestGroupTotal = ( int ) $ groupTotal - ( int ) $ ceilSuiteGroupTotal ;
164
+ $ ceilTestGroupTotal = $ groupTotal - $ ceilSuiteGroupTotal ;
154
165
155
- if ($ ceilTestGroupTotal === 0 ) {
166
+ if ($ ceilTestGroupTotal == 0 ) {
156
167
$ ceilTestGroupTime = 0 ;
157
168
} else {
158
169
$ ceilTestGroupTime = ceil (array_sum ($ testNameToSize ) / $ ceilTestGroupTotal );
@@ -161,15 +172,15 @@ private function getSuiteGroupCounts($suiteNameToTestSize, $testNameToSize, $gro
161
172
// Set suite group total to ceiling
162
173
$ suiteNameToGroupCount = $ ceilSuiteNameToGroupCount ;
163
174
164
- if (isset ($ floorSuiteGroupTime ) && $ ceilSuiteGroupTime !== $ floorSuiteGroupTime ) {
175
+ if (isset ($ floorSuiteGroupTime ) && $ ceilSuiteGroupTime != $ floorSuiteGroupTime ) {
165
176
// Calculate test group time for floor
166
177
$ floorSuiteNameToGroupCount = $ this ->getSuiteGroupCountFromGroupTime (
167
178
$ suiteNameToTestSize ,
168
179
$ floorSuiteGroupTime
169
180
);
170
181
$ floorSuiteGroupTotal = array_sum ($ floorSuiteNameToGroupCount );
171
182
$ floorTestGroupTotal = $ groupTotal - $ floorSuiteGroupTotal ;
172
- if ($ floorTestGroupTotal === 0 ) {
183
+ if ($ floorTestGroupTotal == 0 ) {
173
184
$ floorTestGroupTime = 0 ;
174
185
} else {
175
186
$ floorTestGroupTime = ceil (array_sum ($ testNameToSize ) / $ floorTestGroupTotal );
@@ -187,6 +198,39 @@ private function getSuiteGroupCounts($suiteNameToTestSize, $testNameToSize, $gro
187
198
return $ suiteNameToGroupCount ;
188
199
}
189
200
201
+ /**
202
+ * Reduce total suite groups to a given $total.
203
+ * This method will reduce 1 from a suite that's greater than 1 repeatedly until sum of all groups reaches $total.
204
+ *
205
+ * @param array $suiteNameToGroupCount
206
+ * @param integer $total
207
+ * @return array
208
+ * @throws FastFailException
209
+ */
210
+ private function reduceSuiteGroupTotal ($ suiteNameToGroupCount , $ total )
211
+ {
212
+ if (count ($ suiteNameToGroupCount ) > $ total ) {
213
+ throw new FastFailException (
214
+ "Invalid parameter 'total': must be equal or greater than {count( $ suiteNameToGroupCount)} "
215
+ );
216
+ }
217
+
218
+ $ done = false ;
219
+ while (!$ done ) {
220
+ foreach ($ suiteNameToGroupCount as $ suite => $ count ) {
221
+ if (array_sum ($ suiteNameToGroupCount ) == $ total ) {
222
+ $ done = true ;
223
+ break ;
224
+ }
225
+ if ($ count > 1 ) {
226
+ $ suiteNameToGroupCount [$ suite ] -= 1 ;
227
+ }
228
+ }
229
+ }
230
+
231
+ return $ suiteNameToGroupCount ;
232
+ }
233
+
190
234
/**
191
235
* Return array contains suitename to number of groups to be split based on time.
192
236
*
@@ -203,7 +247,7 @@ private function getSuiteGroupCountFromGroupTime($suiteNameToTestSize, $time)
203
247
if ($ suiteTime <= $ time ) {
204
248
$ suiteNameToGroupCount [$ suiteName ] = 1 ;
205
249
} else {
206
- $ suiteNameToGroupCount [$ suiteName ] = min (ceil ($ suiteTime /$ time ), $ maxCount );
250
+ $ suiteNameToGroupCount [$ suiteName ] = min (( int ) ceil ($ suiteTime /$ time ), $ maxCount );
207
251
}
208
252
}
209
253
return $ suiteNameToGroupCount ;
@@ -218,6 +262,10 @@ private function getSuiteGroupCountFromGroupTime($suiteNameToTestSize, $time)
218
262
*/
219
263
private function splitTestsIntoGroups ($ tests , $ groupCnt )
220
264
{
265
+ if (empty ($ tests )) {
266
+ return [];
267
+ }
268
+
221
269
// Reverse sort the test array by size
222
270
uasort ($ tests , function ($ a , $ b ) {
223
271
return $ a >= $ b ? -1 : 1 ;
@@ -247,7 +295,7 @@ private function splitSuitesIntoGroups($suiteNameToTestSize, $suiteNameToGroupCo
247
295
$ groups = [];
248
296
foreach ($ suiteNameToTestSize as $ suiteName => $ suiteTests ) {
249
297
$ suiteCnt = $ suiteNameToGroupCount [$ suiteName ];
250
- if ($ suiteCnt === 1 ) {
298
+ if ($ suiteCnt == 1 ) {
251
299
$ groups [][$ suiteName ] = array_sum ($ suiteTests );
252
300
$ this ->addSuiteToConfig ($ suiteName , null , $ suiteTests );
253
301
} elseif ($ suiteCnt > 1 ) {
0 commit comments