ujian
Setiap kali anda menulis baris tambahan kod, anda menambah potensi pepijat baharu. Untuk membina atur cara yang lebih baik dan lebih dipercayai, anda perlu menggunakan ujian fungsian dan unit pada kod anda.
Rangka kerja ujian PHPUnit ¶
Symfony menyepadukan perpustakaan kelas bebas - bernama PHPUnit - untuk membawakan anda rangka kerja ujian yang kaya. Bab ini tidak merangkumi PHPUnit itu sendiri, tetapi ia mempunyai dokumentasi yang sangat baik sendiri.
Adalah disyorkan untuk menggunakan versi stabil terkini PHPUnit, pasang PHAR.
Setiap ujian – sama ada ujian unit atau ujian berfungsi – ialah kelas PHP, disimpan dalam Tests/
subdirektori Himpunan anda. Jika anda mengikuti prinsip ini, maka apabila menjalankan semua ujian peringkat program, jalankan sahaja arahan berikut:
1 | $ phpunit |
PHPunit dikonfigurasikan melalui fail phpunit.xml.dist
dalam direktori akar Symfony. phpunit.xml.dist
文件进行配置。
代码覆盖(code coverage)可以通过 —coverage-*
选项来生成。要查看帮助信息,可使用 —help
来显示更多内容。
单元测试 ¶
单元测试是针对单一PHP类的测试,这个类也被称为“单元(unit)”。如果你需要测试你的应用程序层级的整体行为,参考[功能测试] (#catalog2)(Functional Tests)。
编写Symfony单元测试和编写标准的PHPUnit单元测试并无不同。假设,你有一个极其简单的类,类名是 Calculator
,位于app bundle的 Util/
目录下:
// src/AppBundle/Util/Calculator.phpnamespace AppBundle\Util; class Calculator{ public function add($a, $b) { return $a + $b; }}
为了测试它,创建一个 CalculatorTest
文件到你的bundle的 tests/AppBundle/Util
目录下:
// tests/AppBundle/Util/CalculatorTest.phpnamespace Tests\AppBundle\Util; use AppBundle\Util\Calculator; class CalculatorTest extends \PHPUnit_Framework_TestCase{ public function testAdd() { $calc = new Calculator(); $result = $calc->add(30, 12); // assert that your calculator added the numbers correctly! $this->assertEquals(42, $result); }}
根据约定, Tests/AppBundle
目录应该复制你的bundle下的单元测试文件所在的目录。因此,如果你要测试的类位于 src/AppBundle/Util
目录下,那么就把测试代码放在 tests/AppBundle/Util/
—liputan-*
. Untuk melihat maklumat bantuan, gunakan —help
untuk memaparkan lebih banyak kandungan. Ujian unit ¶
🎜Ujian unit ialah ujian untuk kelas PHP tunggal juga Ia dipanggil "unit". Jika anda perlu menguji kelakuan keseluruhan hierarki aplikasi anda, lihat Ujian Fungsian (#catalog2). 🎜🎜Menulis ujian unit Symfony tidak berbeza dengan menulis ujian unit PHPUnit standard. Katakan, anda mempunyai kelas yang sangat mudah bernamaKalkulator
, terletak dalam direktori Util/
app bundle: 🎜# run all tests of the application# 运行程序中的所有测试$ phpunit # run all tests in the Util directory# 运行指定目录下的所有测试$ phpunit tests/AppBundle/Util # run tests for the Calculator class# 仅运行Calculator类的测试$ phpunit tests/AppBundle/Util/CalculatorTest.php # run all tests for the entire Bundle# 运行整个bundle的测试$ phpunit tests/AppBundle/🎜Untuk mengujinya, buat
CalculatorTest< /code> ke direktori tests/AppBundle/Util
bundle anda:
🎜// tests/AppBundle/Controller/PostControllerTest.phpnamespace Tests\AppBundle\Controller; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; class PostControllerTest extends WebTestCase{
public function testShowPost()
{
$client = static::createClient(); $crawler = $client->request('GET', '/post/hello-world'); $this->assertGreaterThan(
0,
$crawler->filter('html:contains("Hello World")')->count()
);
}}
🎜
🎜🎜 Mengikut konvensyen, direktori Tests/AppBundle
hendaklah disalin ke direktori tempat fail ujian unit di bawah berkas anda berada. Oleh itu, jika kelas yang anda ingin uji terletak dalam direktori src/AppBundle/Util
, kemudian letakkan kod ujian dalam direktori tests/AppBundle/Util/
. 🎜🎜
Sama seperti aplikasi sebenar anda – autoloading didayakan secara automatik melalui fail bootstrap.php.cache
(bahagian konfigurasi ini ada dalam app/phpunit.xml secara lalai. fail dist) bootstrap.php.cache
文件来完成(这部分的配置默认是在app/phpunit.xml.dist文件中)
针对指定文件或目录的测试也很简单:
<?xml version="1.0" charset="utf-8" ?><phpunit>
<php>
<server name="KERNEL_DIR" value="/path/to/your/app/" />
</php>
<!-- ... --></phpunit>
功能测试 ¶
功能测试(Functional tests)检查程序不同层面的整合情况(从路由到视图)。这些层面本身并不因PHPUnit的介入而发生改变,只不过它们有着独特的工作流:
制造一个请求(request);
测试响应(response);
点击一个链接,或提交一个表单;
测试响应;
清除然后重复。
你的第一个功能测试 ¶
功能测试是存放在 Test/AppBundle/Controller
目录下的普通PHP文件。如果要测试由你的 PostController
处理的页面,先创建一个新的PostControllerTest.php文件,并继承一个特殊的 WebTestCase
类。
作为例程,这个测试看起来可能像下面代码:
1
为了运行上面的功能测试, WebTestCase
类启动了程序内核。在多数情况下,这是自动完成的。但如果kernel位于非标准目录,你需要调整 phpunit.xml.dist
文件,重新设置 KERNEL_DIR
环境变量为你的kernel目录:
$crawler = $client->request('GET', '/post/hello-world');
createClient()
Ujian untuk fail atau direktori yang ditentukan juga sangat mudah: $link = $crawler
->filter('a:contains("Greet")') // 选择所有含有"Greet"文本之链接
->eq(1) // 结果列表中的第二个
->link() // 点击它; $crawler = $client->click($link);
Ujian fungsional ¶Fungsi Semakan ujian fungsional penyepaduan peringkat program yang berbeza (dari penghalaan kepada paparan). Tahap ini sendiri tidak berubah disebabkan oleh campur tangan PHPUnit, tetapi mereka mempunyai aliran kerja yang unik: - Buat permintaan
Uji respons (respons ); li>Klik pautan, atau serahkan borang Uji respons Kosongkan dan ulangi. Ujian fungsi pertama anda ¶
Ujian fungsian Ia adalah fail PHP biasa yang disimpan dalam direktori Test/AppBundle/Controller
. Jika anda ingin menguji halaman yang dikendalikan oleh PostController
anda, mula-mula buat fail PostControllerTest.php baharu dan warisi kelas WebTestCase
khas. 🎜🎜Sebagai rutin, ujian ini mungkin kelihatan seperti kod berikut: 🎜$form = $crawler->selectButton('submit')->form(); // 设置一些值$form['name'] = 'Lucas';$form['form_name[subject]'] = 'Hey there!'; // 提交表单$crawler = $client->submit($form);
🎜🎜🎜🎜Untuk menjalankan ujian berfungsi di atas, WebTestCase
kelas dimulakan Kernel program. Dalam kebanyakan kes, ini dilakukan secara automatik. Tetapi jika kernel terletak dalam direktori bukan standard, anda perlu melaraskan fail phpunit.xml.dist
dan menetapkan semula pembolehubah persekitaran KERNEL_DIR
ke direktori kernel anda: 🎜 🎜🎜🎜🎜// Assert that the response matches a given CSS selector.// 断言响应内容匹配到一个指定的CSS拾取器$this->assertGreaterThan(0, $crawler->filter('h1')->count());
🎜 Kaedah createClient()
mengembalikan klien, yang boleh digunakan untuk mensimulasikan penyemak imbas supaya anda boleh merangkak halaman tapak web: 🎜🎜🎜🎜🎜🎜🎜🎜🎜🎜🎜🎜🎜🎜🎜🎜 🎜$this->assertContains(
'Hello World',
$client->getResponse()->getContent());
🎜🎜🎜🎜🎜kaedah permintaan() (rujuk Lagi kaedah permintaan request()方法
(参考 更多请求方法)返回了一个 Crawler
对象,用于从响应内容中选择元素(select elements),完成点击链接或提交表单这样的动作。
响应信息必须是XML或HTML文档格式,抓取器(Crawler)才会工作。若需要不带文档格式的纯响应内容(raw content),请使用 $client->getResponse()->getContent()
。
需要点击链接时,先用抓取器选择它,可使用XPath表达式或CSS拾取器来完成选 择,然后再使用client行为来点击它:
use Symfony\Component\HttpFoundation\Response; // ... // Assert that there is at least one h2 tag// with the class "subtitle"// 断言至少有一个h2标签,其class是subtitle$this->assertGreaterThan(
0,
$crawler->filter('h2.subtitle')->count()); // Assert that there are exactly 4 h2 tags on the page// 断言页面有4个h2标签$this->assertCount(4, $crawler->filter('h2')); // Assert that the "Content-Type" header is "application/json"// 断言Content-Type头是application/json$this->assertTrue(
$client->getResponse()->headers->contains(
'Content-Type',
'application/json'
)); // Assert that the response content contains a string// 断言响应信息中包含一个字符串$this->assertContains('foo', $client->getResponse()->getContent());// ...or matches a regex$this->assertRegExp('/foo(bar)?/', $client->getResponse()->getContent()); // Assert that the response status code is 2xx// 断言响应状态码是2xx$this->assertTrue($client->getResponse()->isSuccessful());// Assert that the response status code is 404// 断言响应状态码是404$this->assertTrue($client->getResponse()->isNotFound());// Assert a specific 200 status code// 断言响应状态码是特殊的200$this->assertEquals(
200, // or Symfony\Component\HttpFoundation\Response::HTTP_OK
$client->getResponse()->getStatusCode()); // Assert that the response is a redirect to /demo/contact// 断言响应是一个指向/demo/contact的跳转$this->assertTrue(
$client->getResponse()->isRedirect('/demo/contact'));// ...or simply check that the response is a redirect to any URL// 或者仅言响应是一个跳转,不管指向的URL是什么$this->assertTrue($client->getResponse()->isRedirect());
提交表单时非常相似:选取一个表单按钮,可选地覆写某些表单项的值,然后提交对应的表单:
1
表单也可以处理上传,它还包含了用于填写不同类型的表单字段的方法(例如 select()
和 tick()
) mengembalikan Crawler
objek, gunakan Untuk memilih elemen daripada kandungan respons, menyelesaikan tindakan seperti mengklik pautan atau menyerahkan borang.
Maklumat respons mestilah dalam format dokumen XML atau HTML dan perangkak (Crawler ) mesti akan berfungsi. Jika anda memerlukan kandungan mentah tanpa format dokumen, sila gunakan $client->getResponse()->getContent()
. Apabila anda perlu mengklik pada pautan, mula-mula pilih dengan grabber Anda boleh menggunakan ekspresi XPath atau pemilih CSS untuk melengkapkan pemilihan, dan kemudian gunakan gelagat klien untuk mengkliknya. :$crawler = $client->request('GET', '/post/hello-world');
Menyerahkan borang adalah sangat serupa: pilih butang borang, secara pilihan menggantikan nilai beberapa item borang, dan kemudian serahkan borang yang sepadan:
#🎜 🎜#request(
$method,
$uri,
array $parameters = array(),
array $files = array(),
array $server = array(),
$content = null,
$changeHistory = true)
Borang juga boleh mengendalikan muat naik, dan ia juga mengandungi kaedah untuk mengisi pelbagai jenis borang medan (seperti < code>select() dan tick()
). Untuk butiran, sila rujuk bahagian berikut
Borang Pernyataan bergunaUntuk membantu anda menguasai ujian secepat mungkin, contoh-contoh berikut menyenaraikan yang paling biasa pernyataan yang digunakan Dan pernyataan ujian yang paling berguna:
// Directly submit a form (but using the Crawler is easier!)// 直接提交表单(但是使用Crawler更容易些)$client->request('POST', '/submit', array('name' => 'Fabien')); // Submit a raw JSON string in the request body// 在请求过程中提交一个JSON原生串$client->request(
'POST',
'/submit',
array(),
array(),
array('CONTENT_TYPE' => 'application/json'),
'{"name":"Fabien"}'); // Form submission with a file upload// 文件上传表单的提交use Symfony\Component\HttpFoundation\File\UploadedFile; $photo = new UploadedFile(
'/path/to/photo.jpg',
'photo.jpg',
'image/jpeg',
123);$client->request(
'POST',
'/submit',
array('name' => 'Fabien'),
array('photo' => $photo)); // Perform a DELETE request and pass HTTP headers// 执行一个DELETE请求并传递HTTP头$client->request(
'DELETE',
'/post/12',
array(),
array(),
array('PHP_AUTH_USER' => 'username', 'PHP_AUTH_PW' => 'pa$$word'));
Pemalar kod status HTTP yang diperkenalkan daripada Symfony 2.4
#🎜🎜 Test Client 🎜🎜#¶Pelanggan ujian mensimulasikan klien HTTP, sama seperti penyemak imbas, yang boleh menjana permintaan untuk program Symfony anda. 1
#🎜#
#🎜🎜##🎜🎜##🎜🎜#$client->insulate();
#🎜🎜##🎜##🎜🎜🎜🎜##🎜 #🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜#Kaedah request()
menerima parameter permintaan HTTP dan parameter URL serta mengembalikan tika Crawler. request()
方法接受一个HTTP请求方式的参数和一个URL参数,返回一个Crawler实例。
对于功能测试来说,写死request链接是最佳实践。如果在测试中生成URL时使用Symfony路由,它将无法侦测到针对此URL页面的任何改变,这可能导致用户体验受到冲击。
使用抓取器来找到响应内容中的DOM元素。这些元素可以被用在点击链接或提交表单等场合:
// the HttpKernel request instance// HttpKernel的请求实例$request = $client->getRequest(); // the BrowserKit request instance// 浏览器组件的请求实例$request = $client->getInternalRequest(); // the HttpKernel response instance// HttpKernel的响应实例$response = $client->getResponse(); // the BrowserKit response instance// 浏览器组件的响应实例$response = $client->getInternalResponse(); $crawler = $client->getCrawler();
此处的 click()
方法和 submit()
方法,都会返回一个 crawler
抓取器对象。这些方法是浏览你的程序页面的最佳方式,因为它们帮你做了很多事,像是从表单中侦测HTTP请求方式,或者给你提供一个很好的API用于文件上传。
在后面的 Crawler 小节中你将学习到更多关于链接Link和表单Form对象的知识。
request
Untuk ujian berfungsi, pengekodan keras pautan permintaan ialah amalan terbaik. Jika anda menggunakan penghalaan Symfony semasa menjana URL dalam ujian anda, ia tidak akan dapat mengesan sebarang perubahan pada halaman URL, yang mungkin mengakibatkan pengalaman pengguna terjejas.