CodeIgniter4 HTTP 测试
功能测试使您可以查看对应用程序的一次调用的结果。这可能是返回单个Web表单的结果,命中API端点等等。这很方便,因为它允许您测试单个请求的整个生命周期,确保路由有效,响应是正确的格式,分析结果等等。
测试类
功能测试要求您所有的测试类都对该CodeIgniter\Test\FeatureTestCase
类进行扩展。由于这扩展了CIDatabaseTestCase,因此您必须始终确保 在执行操作之前调用parent::setUp()
和parent::tearDown()
。
<?php namespace App;
use CodeIgniter\Test\FeatureTestCase;
class TestFoo extends FeatureTestCase
{
public function setUp()
{
parent::setUp();
}
public function tearDown()
{
parent::tearDown();
}
}
请求页面
本质上,FeatureTestCase仅允许您在应用程序上调用终结点并返回结果。为此,您可以使用call()
方法。第一个参数是要使用的HTTP方法(最常见的是GET或POST)。第二个参数是您网站上要测试的路径。第三个参数接受一个数组,该数组用于填充您正在使用的HTTP动词的超全局变量。因此,GET方法将填充$ _GET变量,而发布请求将填充$ _POST数组。
// Get a simple page
$result = $this->call('get', site_url());
// Submit a form
$result = $this->call('post', site_url('contact'), [
'name' => 'Fred Flintstone',
'email' => 'flintyfred@example.com'
]);
存在用于每个HTTP动词的简写方法,以简化键入并使内容更清晰:
$this->get($path, $params);
$this->post($path, $params);
$this->put($path, $params);
$this->patch($path, $params);
$this->delete($path, $params);
$this->options($path, $params);
注解
$ params数组并不是每个HTTP动词都有意义,但为了保持一致性而包含了该数组。
设定不同的路线
您可以通过将“路线”数组传递给withRoutes()
方法来使用路线的自定义集合。这将覆盖系统中的所有现有路由:
$routes = [
[ 'get', 'users', 'UserController::list' ]
];
$result = $this->withRoutes($routes)
->get('users');
每个“路由”都是一个3元素数组,包含HTTP动词(或全部为“添加”),要匹配的URI和路由目的地。
设置会话值
您可以使用方法设置自定义会话值,以在单个测试中使用withSession()
。发出此请求时,这需要键/值对的数组,这些键/值对应存在于$ _SESSION变量中。这对于测试身份验证非常方便。
$values = [
'logged_in' => 123
];
$result = $this->withSession($values)
->get('admin');
绕过事件
事件很容易在您的应用程序中使用,但在测试过程中可能会出现问题。尤其是用于发送电子邮件的事件。您可以使用以下skipEvents()
方法告诉系统跳过任何事件处理:
$result = $this->skipEvents()
->post('users', $userInfo);
测试响应
执行一个 call()
并获得结果后,可以在测试中使用许多新的断言。
注解
响应对象可从公开获得$result-&response
。如果需要,可以使用该实例对它执行其他声明。
检查响应状态
isOK()
根据响应是否被认为是“ ok”,返回布尔值true / false。这主要由200或300的响应状态代码确定。
if ($result->isOK())
{
...
}
assertOK()
该论断仅使用isOK()方法来测试响应。
$this->assertOK();
isRedirect()
根据响应是否为重定向响应,返回布尔值true / false。
if ($result->isRedirect())
{
...
}
assertRedirect()
论断该响应是RedirectResponse的一个实例。
$this->assertRedirect();
assertStatus(int $code)
论断返回的HTTP状态代码与$ code相匹配。
$this->assertStatus(403);
会议断言
assertSessionHas(string $key, $value = null)
断言结果会话中存在值。如果传递了$ value,还将断言该变量的值与指定的值匹配。
$this->assertSessionHas('logged_in', 123);
assertSessionMissing(string $key)
断言结果会话不包含指定的$ key。
$this->assertSessionMissin('logged_in');
标头断言
assertHeader(string $key, $value = null)
断言响应中存在名为$ key的标头。如果$ value不为空,还将断言这些值匹配。
$this->assertHeader('Content-Type', 'text/html');
assertHeaderMissing(string $key)
断言响应中不存在标头名称$ key。
$this->assertHeader('Accepts');
Cookie断言
assertCookie(string $key, $value = null, string $prefix = ‘’)
断言响应中存在一个名为$ key的cookie 。如果$ value不为空,还将断言这些值匹配。您可以根据需要通过将cookie前缀作为第三个参数传递来设置它。
$this->assertCookie('foo', 'bar');
assertCookieMissing(string $key)
断言响应中不存在名为$ key的cookie 。
$this->assertCookieMissing('ci_session');
assertCookieExpired(string $key, string $prefix = ‘’)
断言存在一个名为$ key的cookie ,但已过期。您可以根据需要通过将cookie前缀作为第二个参数传递来设置它。
$this->assertCookieExpired('foo');
DOM论断
您可以执行测试,以查看带有以下声明的响应的正文中是否存在特定的元素/文本/等。
assertSee(string $search = null, string $element = null)
断言文本/ HTML是否在页面上,无论是本身,还是(更具体而言)在标签内,由类型,类或id指定:
// Check that "Hello World" is on the page
$this->assertSee('Hello World');
// Check that "Hello World" is within an h1 tag
$this->assertSee('Hello World', 'h1');
// Check that "Hello World" is within an element with the "notice" class
$this->assertSee('Hello World', '.notice');
// Check that "Hello World" is within an element with id of "title"
$this->assertSee('Hellow World', '#title');
assertDontSee(string $search = null, string $element = null)
声明与assertSee()方法完全相反的地方:
// Checks that "Hello World" does NOT exist on the page
$results->dontSee('Hello World');
// Checks that "Hello World" does NOT exist within any h1 tag
$results->dontSee('Hello World', 'h1');
assertSeeElement(string $search)
与assertSee()类似,但是这仅检查现有元素。它不检查特定的文本:
// Check that an element with class 'notice' exists
$results->seeElement('.notice');
// Check that an element with id 'title' exists
$results->seeElement('#title')
assertDontSeeElement(string $search)
与assertSee()类似,但是这仅检查缺少的现有元素。它不检查特定的文本:
// Verify that an element with id 'title' does NOT exist
$results->dontSeeElement('#title');
assertSeeLink(string $text, string $details=null)
断言找到一个匹配标签为$ text的锚标签:
// Check that a link exists with 'Upgrade Account' as the text::
$results->seeLink('Upgrade Account');
// Check that a link exists with 'Upgrade Account' as the text, AND a class of 'upsell'
$results->seeLink('Upgrade Account', '.upsell');
assertSeeInField(string $field, string $value=null)
断言输入标签具有名称和值:
// Check that an input exists named 'user' with the value 'John Snow'
$results->seeInField('user', 'John Snow');
// Check a multi-dimensional input
$results->seeInField('user[name]', 'John Snow');
使用JSON
响应通常包含JSON响应,尤其是在使用API方法时。以下方法可以帮助测试响应。
getJSON()
此方法将以JSON字符串的形式返回响应的主体:
// Response body is this:
['foo' => 'bar']
$json = $result->getJSON();
// $json is this:
{
"foo": "bar"
}
注解
请注意,JSON字符串将漂亮地打印在结果中。
assertJSONFragment(array $fragment)
断言$fragment在JSON响应中找到。它不需要匹配整个JSON值。
// Response body is this:
[
'config' => ['key-a', 'key-b']
]
// Is true
$this->assertJSONFragment(['config' => ['key-a']);
注解
这只是使用phpUnit自己的assertArraySubset() 方法进行比较。
assertJSONExact($test)
与assertJSONFragment()相似,但是检查整个JSON响应以确保完全匹配。
使用XML
getXML()
如果您的应用程序返回XML,则可以通过此方法检索它。