Merge pull request #19307 from eileenmcnaughton/534
[civicrm-core.git] / tests / phpunit / CiviTest / CiviTestSuite.php
1 <?php
2 /**
3 * File for the CiviTestSuite class
4 *
5 * (PHP 5)
6 *
7 * @copyright Copyright CiviCRM LLC (C) 2009
8 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html
9 * GNU Affero General Public License version 3
10 * @package CiviCRM
11 *
12 * This file is part of CiviCRM
13 *
14 * CiviCRM is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Affero General Public License
16 * as published by the Free Software Foundation; either version 3 of
17 * the License, or (at your option) any later version.
18 *
19 * CiviCRM is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Affero General Public License for more details.
23 *
24 * You should have received a copy of the GNU Affero General Public
25 * License along with this program. If not, see
26 * <http://www.gnu.org/licenses/>.
27 */
28
29 /**
30 * Parent class for test suites
31 *
32 * @package CiviCRM
33 */
34 class CiviTestSuite extends PHPUnit\Framework\TestSuite {
35
36 /**
37 * Simple name based constructor.
38 * @param string $theClass
39 * @param string $name
40 */
41 public function __construct($theClass = '', $name = '') {
42 if (empty($name)) {
43 $name = str_replace('_',
44 ' ',
45 get_class($this)
46 );
47
48 // also split AllTests to All Tests
49 $name = str_replace('AllTests', 'All Tests', $name);
50 }
51 parent::__construct($name);
52
53 // also load the class loader
54 require_once 'CRM/Core/ClassLoader.php';
55 CRM_Core_ClassLoader::singleton()->register();
56 }
57
58 /**
59 * suppress failed test error issued by phpunit when it finds.
60 * a test suite with no tests
61 */
62 public function testNothing() {
63 }
64
65 /**
66 * @param $myfile
67 * @return \PHPUnit_Framework_TestSuite
68 */
69 protected function implSuite($myfile) {
70 $name = str_replace('_',
71 ' ',
72 get_class($this)
73 );
74
75 // also split AllTests to All Tests
76 $name = str_replace('AllTests', 'All Tests', $name);
77
78 $suite = new PHPUnit\Framework\TestSuite($name);
79 $this->addAllTests($suite, $myfile,
80 new SplFileInfo(dirname($myfile))
81 );
82 return $suite;
83 }
84
85 /**
86 * Add all test classes *Test and all test suites *Tests in subdirectories
87 *
88 * @param PHPUnit\Framework\TestSuite $suite
89 * Test suite object to add tests to
90 * @param $myfile
91 * @param SplFileInfo $dirInfo
92 * object to scan
93 *
94 * @return void
95 */
96 protected function addAllTests(
97 PHPUnit\Framework\TestSuite &$suite,
98 $myfile, SplFileInfo $dirInfo
99 ) {
100 //echo get_class($this)."::addAllTests($myfile,".$dirInfo->getRealPath().")\n";
101 if (!$dirInfo->isReadable()
102 || !$dirInfo->isDir()
103 ) {
104 return;
105 }
106
107 // Pass 1: Check all *Tests.php files
108 // array(callable)
109 $addTests = [];
110 //echo "start Pass 1 on {$dirInfo->getRealPath()}\n";
111 $dir = new DirectoryIterator($dirInfo->getRealPath());
112 foreach ($dir as $fileInfo) {
113 if ($fileInfo->isReadable() && $fileInfo->isFile()
114 && preg_match('/Tests.php$/',
115 $fileInfo->getFilename()
116 )
117 ) {
118 if ($fileInfo->getRealPath() == $myfile) {
119 // Don't create an infinite loop
120 //echo "ignoring {$fileInfo->getRealPath()}\n";
121 continue;
122 }
123 //echo "checking file ".$fileInfo->getRealPath( )."\n";
124 // This is a file with a name ending in 'Tests.php'.
125 // Get all classes defined in the file and add those
126 // with a class name ending in 'Test' to the test suite
127 $oldClassNames = get_declared_classes();
128 require_once $fileInfo->getRealPath();
129 $newClassNames = get_declared_classes();
130 foreach (array_diff($newClassNames,
131 $oldClassNames
132 ) as $name) {
133 if (preg_match('/Tests$/', $name)) {
134 $addTests[] = $name . '::suite';
135 }
136 }
137 }
138 }
139 sort($addTests);
140 foreach ($addTests as $addTest) {
141 $suite->addTest(call_user_func($addTest));
142 }
143
144 // Pass 2: Scan all subdirectories
145 // array(array(0 => $suite, 1 => $file, 2 => SplFileinfo))
146 $addAllTests = [];
147 $dir = new DirectoryIterator($dirInfo->getRealPath());
148 //echo "start Pass 2 on {$dirInfo->getRealPath()}\n";
149 foreach ($dir as $fileInfo) {
150 if ($fileInfo->isDir()
151 && (substr($fileInfo->getFilename(), 0, 1) != '.')
152 ) {
153 // This is a directory that may contain tests so scan it
154 $addAllTests[] = clone $fileInfo;
155 }
156 }
157 //$addAllTests = CRM_Utils_Array::crmArraySortByField($addAllTests, '1');
158 usort($addAllTests, function ($a, $b) {
159 return strnatcmp($a->getRealPath(), $b->getRealPath());
160 });
161 foreach ($addAllTests as $addAllTest) {
162 $this->addAllTests($suite, $myfile, $addAllTest);
163 }
164
165 // Pass 3: Check all *Test.php files in this directory
166 //echo "start Pass 3 on {$dirInfo->getRealPath()}\n";
167 // array(className)
168 $addTestSuites = [];
169 $dir = new DirectoryIterator($dirInfo->getRealPath());
170 foreach ($dir as $fileInfo) {
171 if ($fileInfo->isReadable() && $fileInfo->isFile()
172 && preg_match('/Test.php$/',
173 $fileInfo->getFilename()
174 )
175 ) {
176 //echo "checking file ".$fileInfo->getRealPath( )."\n";
177 // This is a file with a name ending in 'Tests?.php'.
178 // Get all classes defined in the file and add those
179 // with a class name ending in 'Test' to the test suite
180 $oldClassNames = get_declared_classes();
181 require_once $fileInfo->getRealPath();
182 $newClassNames = get_declared_classes();
183 foreach (array_diff($newClassNames,
184 $oldClassNames
185 ) as $name) {
186 if (strpos($fileInfo->getRealPath(), strtr($name, '_\\', '//') . ".php") !== FALSE) {
187 if (preg_match('/Test$/', $name)) {
188 $addTestSuites[] = $name;
189 }
190 }
191 }
192 }
193 }
194 sort($addTestSuites);
195 foreach ($addTestSuites as $addTestSuite) {
196 $suite->addTestSuite($addTestSuite);
197 }
198
199 // print_r(array($prefix, 'addTests' => $addTests, 'addAllTests' => $addAllTests, 'addTestSuites' => $addTestSuites));
200 }
201
202 }