php PHPUnit:如何为我的所有测试创建一个要调用一次的函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7158930/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHPUnit: How do I create a function to be called once for all my tests?
提问by snakile
I have a PHPUnit test case class (consisting of some test functions). I would like to write a oneTimeSetUp()
function to be called once for all my tests in the class (unlike the standard setUp()
function which is called once for each test in the class). In other words, I'm looking for a PHPUnit equivalent to the JUnit @BeforeClass
annotation.
我有一个 PHPUnit 测试用例类(由一些测试函数组成)。我想编写一个oneTimeSetUp()
函数,为类中的所有测试调用一次(与setUp()
为类中的每个测试调用一次的标准函数不同)。换句话说,我正在寻找一个等同于JUnit @BeforeClass
annotation的 PHPUnit 。
Same question with a oneTimeTearDown()
function.
与oneTimeTearDown()
函数相同的问题。
Is it possible to do so in PHPUnit?
在 PHPUnit 中可以这样做吗?
回答by borrible
回答by Iannazzi
I came to this page with the same question, however the accepted answer is ran on all classes, and for me was not the correct answer.
我带着同样的问题来到这个页面,但是接受的答案是在所有课程中运行的,对我来说不是正确的答案。
If you are like me, your first "Integration test" is to clear out the DB, and run migrations. This gets yourself at a database baseline for all test. I am constantly changing migration files at this point, so setting up the baseline is truly part of all tests.
如果您像我一样,您的第一个“集成测试”就是清除数据库并运行迁移。这使您自己处于所有测试的数据库基线。此时我会不断更改迁移文件,因此设置基线确实是所有测试的一部分。
The migration takes a while, so I do not want it run on all tests.
迁移需要一段时间,所以我不希望它在所有测试中运行。
Then I needed to build up the database testing each piece. I need to write an order test, but first I need to create some products and test that, then I need to test an import fuction.
然后我需要建立测试每个部分的数据库。我需要编写一个订单测试,但首先我需要创建一些产品并对其进行测试,然后我需要测试一个导入功能。
So, what I did is SUPER easy, but not explained extremely well on the internet. I created a simple test to setup the database. Then in your phpspec.xml file add a testsuite....
所以,我所做的非常简单,但在互联网上并没有很好地解释。我创建了一个简单的测试来设置数据库。然后在您的 phpspec.xml 文件中添加一个测试套件....
<testsuite name="Products">
<file>tests/in/SystemSetupTest.php</file>
<file>tests/in/ProductTest.php</file>
<file>tests/in/ProductImportTest.php</file>
</testsuite>
And in the the SystemSetupTest.php ....
并在 SystemSetupTest.php ....
class SystemSetupTest extends ApiTester
{
/** @test */
function system_init()
{
fwrite(STDOUT, __METHOD__ . "\n");
self::createEM(); //this has all the code to init the system...
}
}
Then execute it like:
然后像这样执行它:
phpunit --testsuite Products
phpunit --testsuite 产品
In the end, its a ton easier. It will allow me to build up my system correctly.
最后,它更容易。它将允许我正确构建我的系统。
Additionally I am using laravel 5. When using setUpBeforeClass()
I end up with bootstrap issues, which I am sure I can fix, but the method I use above works perfect.
此外,我使用的是 laravel 5。使用时,setUpBeforeClass()
我最终遇到了引导程序问题,我确信我可以解决这个问题,但我上面使用的方法很完美。
回答by Dane Powell
setUpBeforeClass()
is the way to do this if all of your tests are literally contained within a single class.
setUpBeforeClass()
如果您的所有测试实际上都包含在一个类中,则是执行此操作的方法。
However, your question sort of implies that you may be using your test class as a base class for multiple test classes. In that case setUpBeforeClass will be run before each one. If you only want to run it once you could guard it with a static variable:
但是,您的问题有点暗示您可能将测试类用作多个测试类的基类。在这种情况下 setUpBeforeClass 将在每个之前运行。如果您只想运行一次,则可以使用静态变量保护它:
abstract class TestBase extends TestCase {
protected static $initialized = FALSE;
public function setUp() {
if (!self::$initialized) {
// Do something once here for _all_ test subclasses.
self::$initialized = TRUE;
}
}
}
A final option might be a test listener.
最后一个选项可能是测试侦听器。
回答by Gus Costa
The bootstrap
option can be used on these cases.
该bootstrap
选项可用于这些情况。
You can call it from the command line
您可以从命令行调用它
phpunit --bootstrap myBootstrap.php
Or put it in the XML file, like this:
或者把它放在 XML 文件中,像这样:
<phpunit bootstrap="myBootstrap.php">
...
</phpunit>
回答by cprn
Expanding on accepted answer:
扩展接受的答案:
None of the setUpBeforeClass()
, tearDownAfterClass()
, @beforeClass
, @afterClass
runs in the object context (static methods). You can work around that restriction by guarding any @before
code with a static property instead, like so:
setUpBeforeClass()
, tearDownAfterClass()
, @beforeClass
, 中没有一个@afterClass
在对象上下文中运行(静态方法)。您可以通过@before
使用静态属性保护任何代码来解决该限制,如下所示:
class MyTest extends PHPUnit\Framework\TestCase
{
private static $ready = false;
/**
* @before
*/
protected function firstSetUp()
{
if (static::$ready))
return;
/* your one time setUp here */
static::$ready = true;
}
}
It can't be used for @after
, however, because there's no way of saying when the last test was called.
@after
但是,它不能用于,因为无法确定上次调用的时间。