MediaWiki master
TestSuiteBuilder.php
Go to the documentation of this file.
1<?php
2
3declare( strict_types = 1 );
4
6
11
12 private static function sortByTimeDescending( TestDescriptor $a, TestDescriptor $b ): int {
13 if ( $a->getDuration() === $b->getDuration() ) {
14 return 0;
15 }
16 return ( $a->getDuration() > $b->getDuration() ? -1 : 1 );
17 }
18
19 private static function smallestGroup( array $suites ): int {
20 $min = 10000;
21 $minIndex = 0;
22 $groups = count( $suites );
23 for ( $i = 0; $i < $groups; $i++ ) {
24 if ( $suites[$i]["time"] < $min ) {
25 $min = $suites[$i]["time"];
26 $minIndex = $i;
27 }
28 }
29 return $minIndex;
30 }
31
32 public function buildSuites( array $testDescriptors, int $groups ): array {
33 $suites = array_fill( 0, $groups, [ "list" => [], "time" => 0 ] );
34 $roundRobin = 0;
35 usort( $testDescriptors, [ self::class, "sortByTimeDescending" ] );
36 foreach ( $testDescriptors as $testDescriptor ) {
37 if ( !$testDescriptor->getFilename() ) {
38 // We didn't resolve a matching file for this test, so we skip it
39 // from the suite here. This only happens for "known" missing test
40 // classes (see PhpUnitXmlManager::EXPECTED_MISSING_CLASSES) - in
41 // all other cases a missing test file will throw an exception during
42 // suite building.
43 continue;
44 }
45 if ( $testDescriptor->getDuration() === 0 ) {
46 // If no explicit timing information is available for a test, we just
47 // drop it round-robin into the next bucket.
48 $nextSuite = $roundRobin;
49 $roundRobin = ( $roundRobin + 1 ) % $groups;
50 } else {
51 // If we have information about the test duration, we try and balance
52 // out the tests suites by having an even amount of time spent on
53 // each suite.
54 $nextSuite = self::smallestGroup( $suites );
55 }
56 $suites[$nextSuite]["list"][] = $testDescriptor->getFilename();
57 $suites[$nextSuite]["time"] += $testDescriptor->getDuration();
58 }
59 return $suites;
60 }
61}
buildSuites(array $testDescriptors, int $groups)