Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
DataFixture.php
Go to the documentation of this file.
1 <?php
11 
12 use PHPUnit\Framework\Exception;
13 
15 {
19  protected $_fixtureBaseDir;
20 
26  private $_appliedFixtures = [];
27 
34  public function __construct($fixtureBaseDir)
35  {
36  if (!is_dir($fixtureBaseDir)) {
37  throw new \Magento\Framework\Exception\LocalizedException(
38  new \Magento\Framework\Phrase("Fixture base directory '%1' does not exist.", [$fixtureBaseDir])
39  );
40  }
41  $this->_fixtureBaseDir = realpath($fixtureBaseDir);
42  }
43 
50  public function startTestTransactionRequest(
51  \PHPUnit\Framework\TestCase $test,
52  \Magento\TestFramework\Event\Param\Transaction $param
53  ) {
54  /* Start transaction before applying first fixture to be able to revert them all further */
55  if ($this->_getFixtures($test)) {
56  if ($this->getDbIsolationState($test) !== ['disabled']) {
57  $param->requestTransactionStart();
58  } else {
59  $this->_applyFixtures($this->_getFixtures($test));
60  }
61  }
62  }
63 
70  public function endTestTransactionRequest(
71  \PHPUnit\Framework\TestCase $test,
72  \Magento\TestFramework\Event\Param\Transaction $param
73  ) {
74  /* Isolate other tests from test-specific fixtures */
75  if ($this->_appliedFixtures && $this->_getFixtures($test)) {
76  if ($this->getDbIsolationState($test) !== ['disabled']) {
77  $param->requestTransactionRollback();
78  } else {
79  $this->_revertFixtures();
80  }
81  }
82  }
83 
89  public function startTransaction(\PHPUnit\Framework\TestCase $test)
90  {
91  $this->_applyFixtures($this->_getFixtures($test));
92  }
93 
97  public function rollbackTransaction()
98  {
99  $this->_revertFixtures();
100  }
101 
110  protected function _getFixtures(\PHPUnit\Framework\TestCase $test, $scope = null)
111  {
112  if ($scope === null) {
113  $annotations = $this->getAnnotations($test);
114  } else {
115  $annotations = $test->getAnnotations()[$scope];
116  }
117  $result = [];
118  if (!empty($annotations['magentoDataFixture'])) {
119  foreach ($annotations['magentoDataFixture'] as $fixture) {
120  if (strpos($fixture, '\\') !== false) {
121  // usage of a single directory separator symbol streamlines search across the source code
122  throw new \Magento\Framework\Exception\LocalizedException(
123  new \Magento\Framework\Phrase('Directory separator "\\" is prohibited in fixture declaration.')
124  );
125  }
126  $fixtureMethod = [get_class($test), $fixture];
127  if (is_callable($fixtureMethod)) {
128  $result[] = $fixtureMethod;
129  } else {
130  $result[] = $this->_fixtureBaseDir . '/' . $fixture;
131  }
132  }
133  }
134  return $result;
135  }
136 
141  private function getAnnotations(\PHPUnit\Framework\TestCase $test)
142  {
143  $annotations = $test->getAnnotations();
144  return array_replace($annotations['class'], $annotations['method']);
145  }
146 
153  protected function getDbIsolationState(\PHPUnit\Framework\TestCase $test)
154  {
155  $annotations = $this->getAnnotations($test);
156  return isset($annotations[DbIsolation::MAGENTO_DB_ISOLATION])
157  ? $annotations[DbIsolation::MAGENTO_DB_ISOLATION]
158  : null;
159  }
160 
167  protected function _applyOneFixture($fixture)
168  {
169  try {
170  if (is_callable($fixture)) {
171  call_user_func($fixture);
172  } else {
173  require $fixture;
174  }
175  } catch (\Exception $e) {
176  throw new Exception(
177  sprintf(
178  "Error in fixture: %s.\n %s\n %s",
179  json_encode($fixture),
180  $e->getMessage(),
181  $e->getTraceAsString()
182  ),
183  500,
184  $e
185  );
186  }
187  }
188 
195  protected function _applyFixtures(array $fixtures)
196  {
197  /* Execute fixture scripts */
198  foreach ($fixtures as $oneFixture) {
199  /* Skip already applied fixtures */
200  if (in_array($oneFixture, $this->_appliedFixtures, true)) {
201  continue;
202  }
203  $this->_applyOneFixture($oneFixture);
204  $this->_appliedFixtures[] = $oneFixture;
205  }
206  }
207 
211  protected function _revertFixtures()
212  {
213  $appliedFixtures = array_reverse($this->_appliedFixtures);
214  foreach ($appliedFixtures as $fixture) {
215  if (is_callable($fixture)) {
216  $fixture[1] .= 'Rollback';
217  if (is_callable($fixture)) {
218  $this->_applyOneFixture($fixture);
219  }
220  } else {
221  $fileInfo = pathinfo($fixture);
222  $extension = '';
223  if (isset($fileInfo['extension'])) {
224  $extension = '.' . $fileInfo['extension'];
225  }
226  $rollbackScript = $fileInfo['dirname'] . '/' . $fileInfo['filename'] . '_rollback' . $extension;
227  if (file_exists($rollbackScript)) {
228  $this->_applyOneFixture($rollbackScript);
229  }
230  }
231  }
232  $this->_appliedFixtures = [];
233  }
234 }
$fixtureBaseDir
Definition: bootstrap.php:15
_getFixtures(\PHPUnit\Framework\TestCase $test, $scope=null)
startTestTransactionRequest(\PHPUnit\Framework\TestCase $test, \Magento\TestFramework\Event\Param\Transaction $param)
Definition: DataFixture.php:50
getDbIsolationState(\PHPUnit\Framework\TestCase $test)
startTransaction(\PHPUnit\Framework\TestCase $test)
Definition: DataFixture.php:89
endTestTransactionRequest(\PHPUnit\Framework\TestCase $test, \Magento\TestFramework\Event\Param\Transaction $param)
Definition: DataFixture.php:70