CRM-17860 - Civi\Test::e2e() - Add builder for end-to-end testing
[civicrm-core.git] / Civi / Test.php
1 <?php
2 namespace Civi;
3
4 use PDO;
5 use PDOException;
6
7 /**
8 * Class Test
9 *
10 * A facade for managing the test environment.
11 */
12 class Test {
13
14 /**
15 * @var array
16 */
17 private static $singletons = array();
18
19 /**
20 * Get the data source used for testing.
21 *
22 * @param string|NULL $part
23 * One of NULL, 'hostspec', 'port', 'username', 'password', 'database'.
24 * @return string|array|NULL
25 * If $part is omitted, return full DSN array.
26 * If $part is a string, return that part of the DSN.
27 */
28 public static function dsn($part = NULL) {
29 if (!isset(self::$singletons['dsn'])) {
30 require_once "DB.php";
31 self::$singletons['dsn'] = \DB::parseDSN(CIVICRM_DSN);
32 }
33
34 if ($part === NULL) {
35 return self::$singletons['dsn'];
36 }
37
38 if (isset(self::$singletons['dsn'][$part])) {
39 return self::$singletons['dsn'][$part];
40 }
41
42 return NULL;
43 }
44
45 /**
46 * Get a connection to the test database.
47 *
48 * @return PDO
49 */
50 public static function pdo() {
51 if (!isset(self::$singletons['pdo'])) {
52 $dsninfo = self::dsn();
53 $host = $dsninfo['hostspec'];
54 $port = @$dsninfo['port'];
55 try {
56 self::$singletons['pdo'] = new PDO("mysql:host={$host}" . ($port ? ";port=$port" : ""),
57 $dsninfo['username'], $dsninfo['password'],
58 array(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE)
59 );
60 }
61 catch (PDOException $e) {
62 echo "Can't connect to MySQL server:" . PHP_EOL . $e->getMessage() . PHP_EOL;
63 exit(1);
64 }
65 }
66 return self::$singletons['pdo'];
67 }
68
69 /**
70 * Create a builder for the headless environment.
71 *
72 * @return \Civi\Test\CiviEnvBuilder
73 *
74 * @code
75 * \Civi\Test::headless()->apply();
76 * \Civi\Test::headless()->sqlFile('ex.sql')->apply();
77 * @endCode
78 */
79 public static function headless() {
80 $civiRoot = dirname(__DIR__);
81 $builder = new \Civi\Test\CiviEnvBuilder('CiviEnvBuilder');
82 $builder
83 ->callback(function ($ctx) {
84 if (CIVICRM_UF !== 'UnitTests') {
85 throw new \RuntimeException("\\Civi\\Test::headless() requires CIVICRM_UF=UnitTests");
86 }
87 $dbName = \Civi\Test::dsn('database');
88 echo "Installing {$dbName} schema\n";
89 \Civi\Test::schema()->dropAll();
90 }, 'headless-drop')
91 ->sqlFile($civiRoot . "/sql/civicrm.mysql")
92 ->sql("DELETE FROM civicrm_extension")
93 ->callback(function ($ctx) {
94 \Civi\Test::data()->populate();
95 }, 'populate');
96 return $builder;
97 }
98
99 /**
100 * Create a builder for end-to-end testing on the live environment.
101 *
102 * @return \Civi\Test\CiviEnvBuilder
103 *
104 * @code
105 * \Civi\Test::e2e()->apply();
106 * \Civi\Test::e2e()->install('foo.bar')->apply();
107 * @endCode
108 */
109 public static function e2e() {
110 $builder = new \Civi\Test\CiviEnvBuilder('CiviEnvBuilder');
111 $builder
112 ->callback(function ($ctx) {
113 if (CIVICRM_UF === 'UnitTests') {
114 throw new \RuntimeException("\\Civi\\Test::e2e() requires a real CMS. Found CIVICRM_UF=UnitTests.");
115 }
116 }, 'e2e-check');
117 return $builder;
118 }
119
120 /**
121 * @return \Civi\Test\Schema
122 */
123 public static function schema() {
124 if (!isset(self::$singletons['schema'])) {
125 self::$singletons['schema'] = new \Civi\Test\Schema();
126 }
127 return self::$singletons['schema'];
128 }
129
130
131 /**
132 * @return \Civi\Test\Data
133 */
134 public static function data() {
135 if (!isset(self::$singletons['data'])) {
136 self::$singletons['data'] = new \Civi\Test\Data('CiviTesterData');
137 }
138 return self::$singletons['data'];
139 }
140
141 /**
142 * Prepare and execute a batch of SQL statements.
143 *
144 * @param string $query
145 * @return bool
146 */
147 public static function execute($query) {
148 $pdo = \Civi\Test::pdo();
149
150 $string = preg_replace("/^#[^\n]*$/m", "\n", $query);
151 $string = preg_replace("/^(--[^-]).*/m", "\n", $string);
152
153 $queries = preg_split('/;\s*$/m', $string);
154 foreach ($queries as $query) {
155 $query = trim($query);
156 if (!empty($query)) {
157 $result = $pdo->query($query);
158 if ($pdo->errorCode() == 0) {
159 continue;
160 }
161 else {
162 var_dump($result);
163 var_dump($pdo->errorInfo());
164 // die( "Cannot execute $query: " . $pdo->errorInfo() );
165 }
166 }
167 }
168 return TRUE;
169 }
170
171 }