# Nette Tester - 愉快的單元測試
即使好的程序員犯錯誤。 一個好的程序員和一個壞的程序員之間的區別是,一個好的人通過使用自動化測試更快地檢測到它。
“一個不測試的人注定要重復他自己的錯誤。”(諺語)
“當我們擺脫一個錯誤,另一個錯誤。”(墨菲定律)
“做測試,做測試,做測試”(MartinIlji?Fowler)
你有沒有在PHP中編寫以下代碼?
~~~
$obj = new MyClass;
$result = $obj->process($input);
var_dump($result);
~~~
所以,你有沒有轉儲一個函數調用結果只是為了檢查它返回應該返回什么? 你肯定每天做很多次。 如果一切正常,你刪除這個代碼,并期望該類不會被打破在未來? 墨菲定律保證相反:-)
事實上,我們寫的測試。 如果我們沒有刪除它,我們可以在任何時候運行它,以驗證一切仍然工作,因為它應該。 你可以隨著時間的推移創建大量的這些測試,所以如果我們能夠自動運行它們將是很好的。 稍微修改測試不需要我們的檢查將是有用的,只是為了能夠檢查自己。
和Nette測試器幫助完全相同。
## 安裝和要求
測試程序需要PHP版本5.3.0或更高版本。
首選的安裝方式是Composer和每個后面的示例假設。 但測試儀可以不使用它,也將在下面顯示。
## 通過Composer安裝
假設您已經啟動并運行Composer,并且一個名為demo的應用程序具有以下結構:
~~~
demo/
├── src/ # application code we want to test
├── tests/ # tests we are writing
├── vendor/
└── composer.json
~~~
在終端中導航到應用程序目錄,并使用Composer將Tester添加為依賴關系:
~~~
cd demo
php composer.phar require --dev nette/tester
~~~
## 手動安裝
從GitHub下載Tester,并通過git clone https://github.com/nette/tester.git 提取或克隆其存儲庫。 我們的演示應用程序的目錄結構現在如下:
~~~
demo/
├── src/ # application code we want to test
├── tester/ # source of downloaded Tester
│ ├── src/
│ ├── tests/
│ ├── ...
│ └── readme.md
│
└── tests/ # tests we are writing
~~~
## 運行測試程序
Nette Tester從命令行運行。 我們可以嘗試,沒有任何參數,它只會顯示幫助摘要。
~~~
cd demo
php vendor/nette/tester/src/tester.php # installation by Composer
php tester/src/tester.php # manual installation
~~~
如果Tester由Composer安裝,我們還可以使用更方便的快捷方式腳本:
~~~
cd demo
vendor/bin/tester # UNIX
vendor\bin\tester.bat # Windows
~~~
## 運行測試
我們的應用程序還沒有測試。 我們創建一個簡單的類進行測試,并將其保存到文件src / Greeting.php
~~~
<?php
class Greeting
{
public function say($name)
{
if (!$name) {
throw new InvalidArgumentException('Invalid name');
}
return "Hello $name";
}
}
~~~
讓我們現在寫一個測試。 我們將它保存到文件tests / greeting.phpt。 不要因其長度而氣餒,后面會展示如何簡化它。
~~~
<?php
use Tester\Assert;
# Load Tester library
require __DIR__ . '/../vendor/autoload.php'; # installation by Composer
require __DIR__ . '/../tester/src/bootstrap.php'; # manual installation
# Load the tested class. Composer or your autoloader surely takes
# care of that in practice.
require __DIR__ . '/../src/Greeting.php';
# Adjust PHP behaviour and enable some Tester features (described later)
Tester\Environment::setup();
$o = new Greeting;
Assert::same( 'Hello John', $o->say('John') ); # we expect the same
Assert::exception(function() use ($o) { # we expect an exception
$o->say('');
}, 'InvalidArgumentException', 'Invalid name');
~~~
測試是寫的,我們可以從命令行第一次運行:
~~~
cd tests
php greeting.phpt
~~~
是的,我們第一次運行測試作為普通PHP腳本。 甚至看起來很普遍,大潛力隱藏在它。 我們可以在IDE中單步測試或通過Web瀏覽器加載它。 第一個運行發現句法錯誤,如果我們沒有輸入錯誤,測試結束,沒有錯誤報告。 讓我們將測試中的斷言更改為Assert :: same('Hi John',$ o-> say('John')); 讓我們看看運行時會發生什么。 隨著應用程序的增長,測試的數量也隨之增長。 逐個運行測試是不切實際的。 我們使用測試儀運行:
~~~
cd demo
tester tests/greeting.phpt # we run a single test
tester tests # we run all tests in directory
~~~
要查看更多測試運行的樣子,讓我們嘗試運行測試測試器本身的所有測試。 它們是其安裝的一部分:
~~~
tester vendor/nette/tester/tests # installation by Composer
tester tester/tests # manual installation
~~~
## 測試結果評價
測試儀在測試期間連續打印測試結果:
。 (點) - 測試通過
s - 測試已跳過
F - 測試失敗
輸出可能如下:
~~~
_____ ___ ___ _____ ___ ___
|_ _/ __)( __/_ _/ __)| _ )
|_| \___ /___) |_| \___ |_|_\ v1.7.0
PHP 5.4.4-14+deb7u7 | 'php-cgi' -n | 8 threads
........s................F.........
-- FAILED: tests/greeting.phpt
Failed: 'Hello John' should be
... 'Hi John'
in src/Framework/Assert.php(370)
in src/Framework/Assert.php(52) Tester\Assert::fail()
in tests/greeting.phpt(6) Tester\Assert::same()
FAILURES! (35 tests, 1 failures, 1 skipped, 1.7 seconds)
~~~
運行35個測試,一個失敗,一個跳過。 如果沒有一個失敗,Tester的退出代碼為零。 非零否則:
## Environment::setup()
在測試中提到了一個有點神秘的Tester \ Environment :: setup()調用。 它有什么作用?
提高錯誤轉儲可讀性(包括著色),否則,將打印默認PHP轉儲
使能檢查斷言在測試中被調用,否則,沒有(例如忘記)斷言的測試也通過
當使用--coverage時自動啟動代碼覆蓋收集器(稍后描述)
使用是可選的,但建議。
## Directories structure
它可能看起來很早談論它,但結構良好的目錄與測試節省了很多工作。 我們通過測試類的命名空間將測試分為子目錄:
~~~
demo/
└── tests/
├── NamespaceOne/
│ ├── MyClass.getUsers.phpt
│ ├── MyClass.setUsers.phpt
│ └── ...
│
├── NamespaceTwo/
│ ├── MyClass.creating.phpt
│ ├── MyClass.dropping.phpt
│ └── ...
│
├── test.one.phpt
├── test.two.phpt
├── ...
└── bootstrap.php
~~~
我們創建一個文件bootstrap.php。 它包含所有測試的公共代碼。 例如類自動加載,環境配置,臨時目錄創建,助手等。 每個測試加載引導程序,并注意僅測試。 引導可以看起來像:
~~~
require __DIR__ . '/../vendor/autoload.php';
Tester\Environment::setup();
date_default_timezone_set('Europe/Prague');
define('TMP_DIR', '/tmp/demo-app-tests');
~~~
運行具有更改的目錄結構的測試沒有區別。 測試人員以遞歸方式查找所有* .phpt測試并運行它們:
~~~
cd demo
tester tests
~~~
但我們可以輕松地運行單個命名空間的測試:
~~~
tester tests/NamespaceOne
~~~
## Assertions
在開始的示例測試中,我們使用了兩個斷言:Assert :: same()和Assert :: exception()。 現在我們介紹所有其他類型,我們解釋如何使用。 它們是Tester \ Assert類的方法,但是為了簡化,我們進一步使用它們而沒有命名空間。
Assert::same($expected, $actual)#
$expected must be the same as $actual. It is the same as PHP operator ===.
Assert::notSame($expected, $actual)#
Opposite to Assert::same().
Assert::equal($expected, $actual)#
$expected must be equal to $actual. Object identities and array keys order are ignored.
Assert::notEqual($expected, $actual)#
Opposite to Assert::equal().
Assert::contains($needle, $actual)#
$actual must contain $needle. If $actual is string, it must contain $needle substring. If it is an array, it must contain $needle item.
Assert::notContains($needle, $actual)#
Opposite to Assert::contains().
Assert::true($value)#
$value must be TRUE, so $value === TRUE.
Assert::truthy($value)#
$value must be truthy, so $value == TRUE.
Assert::false($value)#
$value must be FALSE, so $value === FALSE.
Assert::falsey($value)#
$value must be falsey, so $value == FALSE.
Assert::count($count, $value)#
$count must be number of elements in $value. Countable is an array or an object implementing Countable.
Assert::null($value)#
$value must be NULL, so $value === NULL.
Assert::nan($value)#
$value must be Not a Number.
Assert::type($type, $value)#
$value must be of given type. As $type we can use string:
array
list – same as the array but keys must start by zero and must be incremented by one
bool
callable
float
int or integer
null
object
resource
scalar
string
class name or object directly then must pass $value instanceof $type
**Assert::exception($callable, $class, $message = NULL)**
在$ callable調用中,必須拋出$ class實例的異常。 如果我們傳遞$ message,那么異常的消息必須匹配(參見Assert :: match())。 如果我們傳遞$ code,異常的代碼必須是相同的。 例如,此測試失敗,因為異常的消息不匹配:
~~~
Assert::exception(function() {
throw new App\InvalidValueException('Zero value');
}, 'App\InvalidValueException', 'Value is to low');
~~~
通過返回拋出的異常,Assert :: exception()是唯一的。 所以我們可以測試一個以前的異常:
~~~
$e = Assert::exception(function() {
throw new MyException('Something is wrong', 0, new RuntimeException);
}, 'MyException', 'Something is wrong');
Assert::type('RuntimeException', $e->getPrevious());
~~~
**Assert::error($callable, $type, $message = NULL)**
如果我們傳遞一個類名為$ type,這個斷言的行為與絕對相同Assert :: exception()。
如果$ type是E _...常量之一(例如E_WARNING),則$ callable在調用時必須生成此錯誤。 如果我們傳遞$ message消息的錯誤必須匹配(見Assert :: match())。 例如:
~~~
Assert::error(function() {
$i++;
}, E_NOTICE, 'Undefined variable: i');
~~~
最后一種可能性,如果$ type是一個數組,$ callable必須生成所有預期的錯誤。 一個例子最好:
~~~
Assert::error(function() {
$a++;
$b++;
}, [
[E_NOTICE, 'Undefined variable: a'],
[E_NOTICE, 'Undefined variable: b'],
]);
~~~
**Assert::noError($callable)**
檢查函數$ callable不會拋出任何PHP警告/通知/錯誤或異常。 它對于測試一段沒有其他斷言的代碼是有用的。
**Assert::match($pattern, $actual)**
$ actual必須匹配到$ pattern。 我們可以使用兩種模式類型:
我們將正則表達式傳遞為$ pattern。 要分隔它,我們必須使用?或#。 不支持其他定界符。 例如,測試$ var必須只包含十六進制數字
~~~
Assert::match( '#^[0-9a-f]$#i', $var );
~~~
其他變體類似于字符串比較,但我們可以在$ pattern中使用一些修飾符:
%a%除了行結束字符以外的任何一個或多個
%a?%零個或多個除了行結束字符之外的任何東西
%A%一個或多個任何東西,包括行尾字符
%A?%零個或多個任何東西,包括行尾字符
%s%除了行尾字符之外的一個或多個空格字符
%s?%零個或多個空白字符,除了行尾字符
%S%除空格之外的一個或多個字符
%S?%零個或多個字符,除了空格外
%c%任何類型的單個字符(行尾除外)
%d%一個或多個數字
%d?%零個或多個數字
%i%有符號整數值
%f%浮點數
%h%一個或多個HEX數字
例子:
~~~
# Again, hexadecimal number test
Assert::match( '%h%', $var );
# Generalized path to file and line number
Assert::match( 'Error in file %a% on line %i%', $errorMessage );
~~~
**Assert::matchFile($file, $actual)**
斷言與Assert :: match()相同,但模式是從$ file加載的。 它對于非常長的字符串測試很有用。 測試文件可讀。
**Assert::fail($message, $actual = NULL, $expected = NULL)**
這種斷言總是失敗。 這只是方便。 我們可以選擇性地傳遞期望值和實際值。
## 失敗的斷言調查
測試器顯示斷言失敗時的錯誤位置。 當我們比較復雜結構時,測試器創建比較值的轉儲并將它們保存到目錄輸出中。 例如,當虛構測試Arrays.recursive.phpt失敗時,轉儲將保存如下:
~~~
demo/
└── tests/
├── output/
│ ├── Arrays.recursive.actual # actual value
│ └── Arrays.recursive.expected # expected value
│
└── Arrays.recursive.phpt # failing test
~~~
我們可以在Tester \ Dumper :: $ dumpDir中更改目錄的名稱。
## 跳過測試
有些測試只能在某些情況下運行。 如果這些情況不能滿足,我們可以跳過測試。 例如,缺少PHP擴展名:
~~~
if (!extension_loaded('DOM')) {
Tester\Environment::skip('Test requires DOM extension to be loaded.');
}
~~~
測試將停止并標記為s - 跳過。 稍后我們將了解如何使用@skip注釋跳過測試。
## 測試用例
我們已經展示了一個簡單的測試,其中斷言在本指南開頭一個接一個。 有時,用這種方式包含斷言來測試類和結構是有用的。 類必須是Tester \ TestCase的后代,我們只是簡單地談論testcase。
~~~
use Tester\Assert;
class GreetingTest extends Tester\TestCase
{
public function testOne() {
Assert::same(......);
}
public function testTwo() {
Assert::match(......);
}
}
# Testing methods run
$testCase = new GreetingTest;
$testCase->run();
~~~
我們可以通過setUp()和tearDown()方法豐富測試用例。 它們在每個測試方法之前/之后調用:
~~~
use Tester\Assert;
class NextTest extends Tester\TestCase
{
public function setUp() {
# Preparation
}
public function tearDown() {
# Clean-up
}
public function testOne() {
Assert::same(......);
}
public function testTwo() {
Assert::match(......);
}
}
# Testing methods run
$testCase = new NextTest;
$testCase->run();
/*
Method calls order
------------------
setUp()
testOne()
tearDown()
setUp()
testTwo()
tearDown()
*/
~~~
有幾個注釋可以幫助我們測試方法。 我們將它們寫入測試方法。
**@throws**
它在測試方法中等同使用Assert :: exception()。 但是符號更易讀:
~~~
/**
* @throws RuntimeException
*/
public function testOne()
{
...
}
/**
* @throws LogicException Wrong argument order
*/
public function testTwo()
{
...
}
~~~
**@dataProvider**
當我們想要多次運行測試方法但是使用不同的參數時,此注釋適合。 作為參數,我們寫方法名,它返回測試方法的參數。 方法必須返回一個數組或Traversable。 簡單示例:
~~~
public function getLoopArgs()
{
return [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
}
/**
* @dataProvider getLoopArgs
*/
public function testLoop($a, $b, $c)
{
...
}
~~~
另一個注釋@dataProvider變體接受一個INI文件的路徑(相對于測試文件)作為參數。 該方法被調用的次數與INI文件中包含的節數一樣多。 文件loop-args.ini:
~~~
[one]
a=1
b=2
c=3
[two]
a=4
b=5
c=6
[three]
a=7
b=8
c=9
~~~
和使用INI文件的方法:
~~~
/**
* @dataProvider loop-args.ini
*/
public function testLoop($a, $b, $c)
{
...
}
~~~
類似地,我們可以將路徑傳遞給PHP腳本而不是INI。 它必須返回數組或Traversable。 文件loop-args.php:
~~~
return [
['a' => 1, 'b' => 2, 'c' => 3],
['a' => 4, 'b' => 5, 'c' => 6],
['a' => 7, 'b' => 8, 'c' => 9],
];
~~~
## 測試文件注釋
我們在測試文件的開頭編寫注釋,并且輸入不區分大小寫。 虛構示例:
~~~
/**
* TEST: Basic database query test.
*
* @dataProvider files/databases.ini
* @exitCode 56
* @phpVersion < 5.5
*/
require __DIR__ . '/../bootstrap.php';
~~~
## TEST:
它實際上不是一個注釋。 它只設置打印失敗或測試日志中的測試名稱。
## @skip
跳過測試。 它是臨時測試停用方便。
## @phpVersion
如果沒有由相應的PHP版本運行,則跳過測試。 我們將注釋寫為@phpVersion [operator]版本。 我們可以省略運算符,默認值為> =。 例子:
~~~
/**
* @phpVersion 5.3.3
* @phpVersion < 5.5
* @phpVersion != 5.4.5
*/
~~~
## @dataProvider
我們將注釋寫為@dataProvider file.ini。 INI文件路徑是相對于測試文件。 測試運行的次數與INI文件中包含的節數一樣多。 讓我們假設INI文件databases.ini:
~~~
[mysql]
dsn = "mysql:host=127.0.0.1"
user = root
password = ******
[postgresql]
dsn = "pgsql:host=127.0.0.1;dbname=test"
user = postgres
password = ******
[sqlite]
dsn = "sqlite::memory:"
~~~
和文件database.phpt在同一目錄中:
~~~
/**
* @dataProvider databases.ini
*/
$args = Tester\Environment::loadData();
~~~
測試運行三次,$ args將包含來自mysql,postgresql或sqlite的值。
當我們用@dataProvider寫一個問號的注釋時,還有一個變體? file.ini。 在這種情況下,如果INI文件不存在,則跳過測試。
注釋的可能性還沒有被提及。 我們可以在INI文件之后寫入條件。 只有在所有條件匹配時,才對給定段進行測試運行。 讓我們擴展INI文件:
~~~
[mysql]
dsn = "mysql:host=127.0.0.1"
user = root
password = ******
[postgresql 8.4]
dsn = "pgsql:host=127.0.0.1;dbname=test"
user = postgres
password = ******
[postgresql 9.1]
dsn = "pgsql:host=127.0.0.1;dbname=test;port=5433"
user = postgres
password = ******
[sqlite]
dsn = "sqlite::memory:"
~~~
我們將使用帶條件的注釋:
~~~
/**
* @dataProvider databases.ini postgresql, >=9.0
*/
~~~
測試對于postgresql 9.1節只運行一次。 其他部分不符合條件。
類似地,我們可以將路徑傳遞給PHP腳本而不是INI。 它必須返回數組或Traversable。 文件databases.php:
~~~
return [
'postgresql 8.4' => [
'dsn' => '...',
'user' => '...',
],
'postgresql 9.1' => [
'dsn' => '...',
'user' => '...',
],
];
~~~
## @multiple
我們將它寫為@multiple N,其中N是整數。 測試運行正好N次。
## @testCase
注釋沒有參數。 我們使用它,當我們寫一個測試作為Tester \ TestCase類。 在這種情況下,測試運行的次數與測試方法的次數一樣多。 每個測試方法分開運行。 它可以大大加快整個測試過程。 我們建議使用此注釋。
## @ exitCode
我們將它寫為@exitCode N,其中N是測試的退出代碼。 例如,如果在測試中調用exit(10),我們將注釋寫為@exitCode 10.如果測試以不同的代碼結束,則認為失敗。 如果我們省略注釋,則驗證退出代碼0(零)
## @ httpCode
僅當PHP二進制是CGI時才評估注釋。 否則忽略。 我們將它寫為@httpCode NNN,其中NNN是預期的HTTP代碼。 如果我們省略注釋,則驗證HTTP代碼200。 如果我們將NNN寫為一個字符串為零,例如any,那么HTTP代碼根本不會被檢查。
## @outputMatch a @ outputMatchFile
注釋的行為與Assert :: match()和Assert :: matchFile()斷言一致。 但是模式是在測試的標準輸出中找到的。 一個合適的用例是當我們假設測試以致命錯誤結束,并且我們需要驗證其輸出。
## @ phpIni
它設置測試的INI配置值。 例如,我們將它寫為@phpIni precision = 20,它的工作方式與通過參數-d precision = 20從命令行傳遞值的方式相同。
## 幫助
**DomQuery**
Tester \ DomQuery類有助于測試HTML或XML內容。 所有方法的說明在API文檔中。 在這里,我們顯示基本用法:
~~~
# HTML which we want to test
$html = $template->render();
# We create DOM structure from HTML
$dom = Tester\DomQuery::fromHtml($html);
# We can test
Assert::true( $dom->has('form#registration') );
Assert::true( $dom->has('input[name="username"]') );
Assert::true( $dom->has('input[name="password"]') );
Assert::true( $dom->has('input[type="submit"]') );
~~~
我們使用CSS選擇DomQuery::有($選擇)參數。
## FileMock
Tester \ FileMock模擬內存中的文件,并幫助您測試使用fopen(),file_get_contents()或parse_ini_file()等函數的代碼。 例如:
~~~
# Tested class
class Logger
{
private $logFile;
public function __construct($logFile)
{
$this->logFile = $logFile;
}
public function log($message)
{
file_put_contents($this->logFile, $message . "\n", FILE_APPEND);
}
}
# New empty file
$file = Tester\FileMock::create('');
$logger = new Logger($file);
$logger->log('Login');
$logger->log('Logout');
# Created content testing
Assert::same( "Login\nLogout\n", file_get_contents($file) );
~~~
**purge()**
Tester \ Helpers類提供方法purge()創建傳遞目錄,但只有當還不存在。 如果是這樣,它清除其所有內容。 它是臨時目錄創建方便。 例如在tests / bootstrap.php:
~~~
@mkdir(__DIR__ . '/tmp'); # @ - directory may already exist
define('TEMP_DIR', __DIR__ . '/tmp/' . getmypid());
Tester\Helpers::purge(TEMP_DIR);
~~~
**lock()**
后來我們了解到測試并行運行。 有時我們不需要重疊測試運行。 通常,數據庫測試需要準備數據庫中的結構和數據,并且它們在測試的運行時間期間不需要干擾它們。 在這些情況下,我們使用Tester \ Environment :: lock($ name,$ dir):
~~~
Tester\Environment::lock('database', __DIR__ . '/tmp');
~~~
第一個參數是鎖名稱。 第二個是保存鎖的目錄路徑。 獲取鎖的測試首先運行。 其他測試必須等待,直到完成。
**Command line options**
通過運行不帶參數的測試程序或使用選項-h,我們獲得命令行選項概述。
**-p <path>**
測試程序使用這個PHP二進制測試運行:
~~~
tester -p /home/user/php-5.5.0/php-cgi tests
~~~
**-c <path>**
該選項與PHP二進制相同。 通過的php.ini用于測試。 默認情況下不使用php.ini。 當我們分發php.ini和測試的例子:
~~~
tester -c tests/php.ini tests
~~~
**-l | –log <path>**
測試的進度寫入文件。 所有失敗,跳過和成功的測試:
~~~
tester -log /var/log/tests.log tests
~~~
**-d <key = value>**
該選項與PHP二進制相同。 它定義了測試的INI值。 該選項可以多次使用。
**-s**
將顯示有關跳過的測試的信息。
**--stop-on-fail**
測試人員在第一次失敗測試時停止測試。
**-j <num>**
測試以<num>并行線程運行。 默認值為8.如果我們希望連續運行測試,則使用值1。
**-o <console | tap | junit | none>**
輸出格式。 默認為控制臺格式。
控制臺:與默認相同,但在這種情況下不打印標志
tap:適用于機器處理的TAP格式(替換--tap選項)
junit:JUnit XML格式,適合機器處理
none:沒有打印
**-w | - watch <path>**
測試程序不會在測試完成后結束,但它會保持運行并且正在查看給定的目錄。 每當目錄更改時,它再次運行測試。 參數可以多次使用。 它在測試寫和調試期間很方便。
**-i | –info**
它顯示有關測試運行環境的信息。 例如:
~~~
tester -p /home/php/php-5.5.6 -c tests/php.ini --info
PHP binary:
/home/php/php-5.5.6
PHP version:
5.5.6 (cli)
Loaded php.ini files:
/var/www/dev/demo/tests/php.ini
Loaded extensions:
Core, ctype, date, dom, ereg, fileinfo, filter, hash, ...
~~~
**--setup <path>**
測試器在開始時加載給定的PHP腳本。 變量測試器\ Runner \ Runner $ runner可用。 讓我們假設文件測試/ runner-setup.php:
~~~
$runner->outputHandlers[] = new MyOutputHandler;
~~~
我們運行測試器:
~~~
tester --setup tests/runner-setup.php tests
~~~
**--colors 1 | 0**
測試儀在默認情況下檢測可著色終端并對其輸出進行著色。 此選項超過自動檢測。 我們可以通過系統環境變量NETTE_TESTER_COLORS全局設置顏色。
**--coverage <path>**
測試人員將生成一個報告,概述測試覆蓋的源代碼有多少。 此選項需要啟用PHP擴展Xdebug,或PHP 7與PHPDBG SAPI更快。 目標文件擴展名確定內容格式。 HTML或Clover XML。
~~~
tester tests --coverage coverage.html # HTML report
tester tests --coverage coverage.xml # Clover XML report
~~~
**--coverage-src <path>**
我們同時使用選項--coverage。 <path>是我們生成報告的源代碼的路徑。
**HHVM support**
測試程序支持HHVM 3.3.0或更高版本。 用法很簡單,只需使用-p選項傳遞HHVM二進制路徑。
~~~
tester -p hhvm
~~~
**Tips**
使用exit()和die()結束測試失敗消息是不好的做法。 例如exit('Error in connection')結束使用退出代碼0(零)的測試,這意味著成功。 始終使用echo'連接錯誤',然后退出(1)。
編寫準確的斷言是方便的Assert :: same($ a,$ b),而不是Assert :: true($ a === $ b)。 僅在第一種情況下,我們得到有意義的錯誤消息。 在另一種情況下,我們得到的FALSE應該只為TRUE,它沒有說明$ a和$ b變量。
使用Assert :: nan()進行NAN(非值)測試。 NAN值非常具體,斷言Assert :: same()或Assert :: equal()可以工作不可預測。
**Own php.ini**
測試器使用-n選項運行PHP進程,因此沒有加載php.ini(甚至不是從UNIX中的/etc/php/conf.d/*.ini加載)。 它確保測試運行的最干凈的環境,但它也取消了系統PHP通常加載的所有外部PHP擴展。
如果您需要一些擴展或一些特殊的INI設置,創建自己的php.ini文件,并在測試中分發它。 然后我們運行帶有-c選項的Tester。 測試器-c測試/ php.ini。 INI文件可能如下所示:
~~~
[PHP]
extension=php_pdo_mysql.dll
extension=php_pdo_pgsql.dll
memory_limit=512M
~~~
- Nette簡介
- 快速開始
- 入門
- 主頁
- 顯示文章詳細頁
- 文章評論
- 創建和編輯帖子
- 權限驗證
- 程序員指南
- MVC應用程序和控制器
- URL路由
- Tracy - PHP調試器
- 調試器擴展
- 增強PHP語言
- HTTP請求和響應
- 數據庫
- 數據庫:ActiveRow
- 數據庫和表
- Sessions
- 用戶授權和權限
- 配置
- 依賴注入
- 獲取依賴關系
- DI容器擴展
- 組件
- 字符串處理
- 數組處理
- HTML元素
- 使用URL
- 表單
- 驗證器
- 模板
- AJAX & Snippets
- 發送電子郵件
- 圖像操作
- 緩存
- 本土化
- Nette Tester - 單元測試
- 與Travis CI的持續集成
- 分頁
- 自動加載
- 文件搜索:Finder
- 原子操作