PHPUnit 过滤不适用于 setUpBeforeClass() 和 tearDownAfterClass()
PHPUnit filtering not working with setUpBeforeClass() and tearDownAfterClass()
我们相当广泛地使用 PHPUnit 过滤,它似乎不会阻止我们在测试 类 中执行与过滤结果不匹配的 setUpBeforeClass() 和 tearDownAfterClass()。
对于那些不知道的人,您可以使用 --filter
选项来过滤您的 PHPUnit 测试。
mocha 等其他测试框架不会执行 fixture,除非它们与过滤器匹配。
首先我想说我非常尊重所有 phpunit 贡献者。
我们的解决方法是开发一个新的基础 class,它提供了一组新的结构,可以用来代替 setUpBeforeClass() 和 tearDownAfterClass()。
class Test extends PHPUnit_Framework_TestCase {
/**
* PHPUnit has a serious design flaw where setUpBeforeClass() and tearDownAfterClass() are still
* executed for all test classes even if they don't match the filter. This appears to be due to
* PHPUnit applying the filter after these fixtures. Fortunately, with a little magic, we can
* define constructs for before() and after() that achieve our desired behavior. Some may say that
* this is not a PHPUnit bug, but other testing frameworks like mocha don't execute any of the
* fixtures unless the filters match.
*/
/**
* @var boolean True if we are executing this test
*/
protected static $executing = false;
/**
* Use instead of setUpBeforeClass() to create a fixture that is called once per test class and
* not called unless it is in the filter results.
*/
public static function before() {}
/**
* Use instead of tearDownAfterClass() to create a fixture that is called once per test class and
* not called unless it is in the filter results.
*/
public static function after() {}
/**
* A base method for setUp() that uses the $executing flag to determine whether or not to run
* before(). We cannot use setUpBeforeClass() here as setUpBeforeClass() will run before any
* filters are applied.
*/
protected function setUp() {
if (!self::$executing) {
static::$executing = true;
static::before();
}
}
/**
* A base method for tearDownAfterClass() that uses the $executing flag to determine whether or
* not to run after()
*/
public static function tearDownAfterClass() {
if (static::$executing) {
// Set to false so that this doesn't trigger execution of another classes fixtures as $executing
// is a static member
static::$executing = false;
static::after();
}
}
}
然后您可以像这样使用新的 before() 和 after() 结构,如果测试不是过滤结果的一部分,它们将不会被执行:
class MyTest extends Test {
public static function before() {
// Code done once before all tests
}
public function testFoo() {
// Test something
}
public static function after() {
// Code done once after all tests
}
}
我们相当广泛地使用 PHPUnit 过滤,它似乎不会阻止我们在测试 类 中执行与过滤结果不匹配的 setUpBeforeClass() 和 tearDownAfterClass()。
对于那些不知道的人,您可以使用 --filter
选项来过滤您的 PHPUnit 测试。
mocha 等其他测试框架不会执行 fixture,除非它们与过滤器匹配。
首先我想说我非常尊重所有 phpunit 贡献者。
我们的解决方法是开发一个新的基础 class,它提供了一组新的结构,可以用来代替 setUpBeforeClass() 和 tearDownAfterClass()。
class Test extends PHPUnit_Framework_TestCase {
/**
* PHPUnit has a serious design flaw where setUpBeforeClass() and tearDownAfterClass() are still
* executed for all test classes even if they don't match the filter. This appears to be due to
* PHPUnit applying the filter after these fixtures. Fortunately, with a little magic, we can
* define constructs for before() and after() that achieve our desired behavior. Some may say that
* this is not a PHPUnit bug, but other testing frameworks like mocha don't execute any of the
* fixtures unless the filters match.
*/
/**
* @var boolean True if we are executing this test
*/
protected static $executing = false;
/**
* Use instead of setUpBeforeClass() to create a fixture that is called once per test class and
* not called unless it is in the filter results.
*/
public static function before() {}
/**
* Use instead of tearDownAfterClass() to create a fixture that is called once per test class and
* not called unless it is in the filter results.
*/
public static function after() {}
/**
* A base method for setUp() that uses the $executing flag to determine whether or not to run
* before(). We cannot use setUpBeforeClass() here as setUpBeforeClass() will run before any
* filters are applied.
*/
protected function setUp() {
if (!self::$executing) {
static::$executing = true;
static::before();
}
}
/**
* A base method for tearDownAfterClass() that uses the $executing flag to determine whether or
* not to run after()
*/
public static function tearDownAfterClass() {
if (static::$executing) {
// Set to false so that this doesn't trigger execution of another classes fixtures as $executing
// is a static member
static::$executing = false;
static::after();
}
}
}
然后您可以像这样使用新的 before() 和 after() 结构,如果测试不是过滤结果的一部分,它们将不会被执行:
class MyTest extends Test {
public static function before() {
// Code done once before all tests
}
public function testFoo() {
// Test something
}
public static function after() {
// Code done once after all tests
}
}