[TASK] Smarter functional test parallelization
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Build / Scripts / splitFunctionalTests.sh
1 #!/bin/bash
2
3 # This file is typically executed by travis and / or bamboo.
4 # It expects to be run from the core document root.
5 #
6 # ./typo3/sysext/core/Build/Scripts/splitFunctionalTests.sh <numberOfConfigs>
7 #
8 # The scripts finds all functional tests and creates <numberOfConfigs> number
9 # of phpunit .xml configuration files where each configuration lists a weighted
10 # number of single functional tests.
11 #
12 # typo3/sysext/core/Build/FunctionalTests-Job-<counter>.xml
13
14
15 numberOfFunctionalTestJobs=${1}
16 numberOfFunctionalTestJobsMinusOne=$(( numberOfFunctionalTestJobs - 1 ))
17
18 # Have a dir for temp files and clean up possibly existing stuff
19 if [ ! -d buildTemp ]; then
20 mkdir buildTemp || exit 1
21 fi
22 if [ -f buildTemp/testFiles.txt ]; then
23 rm buildTemp/testFiles.txt
24 fi
25 if [ -f buildTemp/testFilesWithNumberOfTestFiles.txt ]; then
26 rm buildTemp/testFilesWithNumberOfTestFiles.txt
27 fi
28 if [ -f buildTemp/testFilesWeighted.txt ]; then
29 rm buildTemp/testFilesWeighted.txt
30 fi
31
32 # A list of all functional test files
33 find . -name \*Test.php -path \*typo3/sysext/*/Tests/Functional* > buildTemp/testFiles.txt
34
35 # File with test files of format "42 ./path/to/file"
36 while read testFile; do
37 numberOfTestsInTestFile=`grep "@test" ${testFile} | wc -l`
38 echo "${numberOfTestsInTestFile} ${testFile}" >> buildTemp/testFilesWithNumberOfTestFiles.txt
39 done < buildTemp/testFiles.txt
40
41 # Sort list of files numeric
42 cat buildTemp/testFilesWithNumberOfTestFiles.txt | sort -n -r > buildTemp/testFilesWeighted.txt
43
44 # Config file boilerplate per job
45 for (( i=0; i<${numberOfFunctionalTestJobs}; i++)); do
46 if [ -f typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml ]; then
47 rm typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
48 fi
49 echo '<phpunit' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
50 echo ' backupGlobals="true"' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
51 echo ' backupStaticAttributes="false"' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
52 echo ' bootstrap="FunctionalTestsBootstrap.php"' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
53 echo ' colors="true"' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
54 echo ' convertErrorsToExceptions="true"' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
55 echo ' convertWarningsToExceptions="true"' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
56 echo ' forceCoversAnnotation="false"' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
57 echo ' processIsolation="true"' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
58 echo ' stopOnError="false"' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
59 echo ' stopOnFailure="false"' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
60 echo ' stopOnIncomplete="false"' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
61 echo ' stopOnSkipped="false"' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
62 echo ' verbose="false"' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
63 echo '>' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
64 echo ' <testsuites>' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
65 echo ' <testsuite name="Core tests">' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
66 done
67
68 counter=0
69 direction=ascending
70 while read testFileWeighted; do
71 # test file only, without leading ./
72 testFile=`echo ${testFileWeighted} | cut -f2 -d" " | cut -f2-40 -d"/"`
73
74 # Goal: with 3 jobs, have:
75 # file #0 to job #0 (asc)
76 # file #1 to job #1 (asc)
77 # file #2 to job #2 (asc)
78 # file #3 to job #2 (desc)
79 # file #4 to job #1 (desc)
80 # file #5 to job #0 (desc)
81 # file #6 to job #0 (asc)
82 # ...
83 testFileModuleNumberOfJobs=$(( counter % numberOfFunctionalTestJobs ))
84 if [[ ${direction} == "descending" ]]; then
85 targetJobNumberForFile=$(( numberOfFunctionalTestJobs - testFileModuleNumberOfJobs))
86 else
87 targetJobNumberForFile=${testFileModuleNumberOfJobs}
88 fi
89 if [ ${testFileModuleNumberOfJobs} -eq ${numberOfFunctionalTestJobs} ]; then
90 if [[ ${direction} == "descending" ]]; then
91 direction=ascending
92 else
93 direction=descending
94 fi
95 fi
96
97 echo ' <directory>' >> typo3/sysext/core/Build/FunctionalTests-Job-${targetJobNumberForFile}.xml
98 echo " ../../../../${testFile}" >> typo3/sysext/core/Build/FunctionalTests-Job-${targetJobNumberForFile}.xml
99 echo ' </directory>' >> typo3/sysext/core/Build/FunctionalTests-Job-${targetJobNumberForFile}.xml
100 (( counter ++ ))
101 done < buildTemp/testFilesWeighted.txt
102
103 # Final part of config file
104 for (( i=0; i<${numberOfFunctionalTestJobs}; i++)); do
105 echo ' </testsuite>' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
106 echo ' </testsuites>' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
107 echo '</phpunit>' >> typo3/sysext/core/Build/FunctionalTests-Job-${i}.xml
108 done
109
110 # Clean up
111 rm buildTemp/testFiles.txt
112 rm buildTemp/testFilesWeighted.txt
113 rm buildTemp/testFilesWithNumberOfTestFiles.txt
114 rmdir buildTemp