2011-08-02 18:12:44 +02:00
|
|
|
@title Writing Unit Tests
|
|
|
|
@group developer
|
|
|
|
|
|
|
|
Simple guide to libphutil, Arcanist and Phabricator unit tests.
|
|
|
|
|
|
|
|
= Overview =
|
|
|
|
|
|
|
|
libphutil, Arcanist and Phabricator provide and use a simple unit test
|
|
|
|
framework. This document is aimed at project contributors and describes how to
|
|
|
|
use it to add and run tests in these projects or other libphutil libraries.
|
|
|
|
|
|
|
|
In the general case, you can integrate ##arc## with a custom unit test engine
|
|
|
|
(like PHPUnit or any other unit testing library) to run tests in other projects.
|
|
|
|
See @{article:Arcanist User Guide: Customizing Lint, Unit Tests and Workflows}
|
|
|
|
for information on customizing engines.
|
|
|
|
|
|
|
|
= Adding Tests =
|
|
|
|
|
|
|
|
To add new tests to a libphutil, Arcanist or Phabricator module:
|
|
|
|
|
|
|
|
- Create a ##__tests__/## directory in the module if it doesn't exist yet.
|
|
|
|
- Add classes to the ##__tests__/## directory which extend from
|
|
|
|
@{class:PhabricatorTestCase} (in Phabricator) or
|
|
|
|
@{class@arcanist:ArcanistPhutilTestCase} (elsewhere).
|
|
|
|
- Run ##arc liberate## on the library root so your classes are loadable.
|
|
|
|
|
|
|
|
= Running Tests =
|
|
|
|
|
|
|
|
Once you've added test classes, you can run them with:
|
|
|
|
|
|
|
|
- ##arc unit path/to/module/##, to explicitly run module tests.
|
|
|
|
- ##arc unit##, to run tests for all modules affected by changes in the
|
|
|
|
working copy.
|
2011-08-03 17:17:53 +02:00
|
|
|
- ##arc diff## will also run ##arc unit## for you.
|
|
|
|
|
|
|
|
= Example Test Case =
|
|
|
|
|
|
|
|
Here's a simple example test:
|
|
|
|
|
|
|
|
lang=php
|
|
|
|
class PhabricatorTrivialTestCase extends PhabricatorTestCase {
|
|
|
|
|
|
|
|
private $two;
|
|
|
|
|
|
|
|
public function willRunOneTest($test_name) {
|
|
|
|
// You can execute setup steps which will run before each test in this
|
|
|
|
// method.
|
|
|
|
$this->two = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testAllIsRightWithTheWorld() {
|
2011-08-03 18:16:50 +02:00
|
|
|
$this->assertEqual(4, $this->two + $this->two, '2 + 2 = 4');
|
2011-08-03 17:17:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
You can see this class at @{class:PhabricatorTrivialTestCase} and run it with:
|
|
|
|
|
|
|
|
phabricator/ $ arc unit src/infrastructure/testing/testcase/
|
|
|
|
PASS <1ms* testAllIsRightWithTheWorld
|
|
|
|
|
|
|
|
For more information on writing tests, see
|
2012-08-10 23:21:51 +02:00
|
|
|
@{class@arcanist:ArcanistPhutilTestCase} and @{class:PhabricatorTestCase}.
|
2011-08-03 17:17:53 +02:00
|
|
|
|
|
|
|
= Database Isolation =
|
|
|
|
|
|
|
|
By default, Phabricator isolates unit tests from the database. It makes a crude
|
|
|
|
effort to simulate some side effects (principally, ID assignment on insert), but
|
|
|
|
any queries which read data will fail to select any rows and throw an exception
|
|
|
|
about isolation. In general, isolation is good, but this can make certain types
|
|
|
|
of tests difficult to write. When you encounter issues, you can deal with them
|
|
|
|
in a number of ways. From best to worst:
|
|
|
|
|
|
|
|
- Encounter no issues; your tests are fast and isolated.
|
|
|
|
- Add more simulated side effects if you encounter minor issues and simulation
|
|
|
|
is reasonable.
|
|
|
|
- Build a real database simulation layer (fairly complex).
|
|
|
|
- Disable isolation for a single test by using
|
|
|
|
##LiskDAO::endIsolateAllLiskEffectsToCurrentProcess();## before your test
|
|
|
|
and ##LiskDAO::beginIsolateAllLiskEffectsToCurrentProcess();## after your
|
|
|
|
test. This will disable isolation for one test. NOT RECOMMENDED.
|
|
|
|
- Disable isolation for your entire test case by overriding
|
|
|
|
##getPhabricatorTestCaseConfiguration()## and providing
|
|
|
|
##self::PHABRICATOR_TESTCONFIG_ISOLATE_LISK => false## in the configuration
|
|
|
|
dictionary you return. This will disable isolation entirely. STRONGLY NOT
|
|
|
|
RECOMMENDED.
|