PHPUnit袖珍指南-第三章 PHPUnit的目的

第三章PHPUnit的目的

到此爲止,我們只有兩個對Array和內建函數sizeof()的測試。當我們開始測試大量的array_*()函數時,每個都需要一個測試。我們可以每個都從頭寫起。但是,更好的方法是一次性寫好一個測試基礎構架,以後就只用寫每個測試不同的部分。PHPUnit就是這樣一個基礎構架。

5展示瞭如何用PHPUnit重寫例4中的兩個測試。

 

5 PHPUnit測試 Arraysizeof().

<?php

require_once 'PHPUnit2/Framework/TestCase.php';

 

class ArrayTest extends PHPUnit2_Framework_TestCase {

  public function testNewArrayIsEmpty( ) {

    // fixture

    $fixture = Array( );

 

    // fixture0

    $this->assertEquals(0, sizeof($fixture)); 

  }

  public function testArrayContainsAnElement( ) { 

    // fixture

            $fixture = Array( );

 

    // fixture

            $fixture[] = 'Element';

 

            //fixture1

            $this->assertEquals(1, sizeof($fixture));

  }

}

?>

 

5告訴我們用PHPUnit來寫測試的基本步驟是:

1.    Class的測試類是ClassTest

2.    ClassTest一般繼承PHPUnit2_ Framework_TestCase

3.    測試是公有方法,沒有參數,名字是test*

4.    在測試方法中,斷言函數,如assertEquals()(見表6)用於斷言實際值是否匹配期望值。

 

一個如PHPUnit的框架需要解決一系列問題,有些看起來互相沖突。測試必須同時滿足以下條件:

 

易學

測試必須容易學,否則,開發人員不會去學

 

易開發

測試必須容易開發,否則,開發人員不會去開發

 

易讀

測試代碼必須沒有外部關係,這樣測試本身不會在雜亂無章中迷失。

 

容易執行

測試應該很容易執行,執行的結果以一種清楚和明確的格式表達出來。

 

快速執行

測試應該執行的很快,這樣每天才能執行上千次。

 

代碼隔離

測試之間不能互相影響,測試順序的改變不應該影響結果。

 

可組合的

我們應該可以以任何組合來運行測試,這是代碼隔離的一個必然結果。

 

這些約束條件有兩個主要的衝突

 

易學vs易開發

測試通常不需要應用到編程全部的靈活性。很多測試工具提供了它們自己的測試腳本語言,這些語言只有書寫測試所需特性的最小集,因爲沒有噪聲來干擾你的測試內容,寫出來的測試易讀易寫。但是學一種新的編織郵件和一套工具還是不方便的,容易混淆視聽。

 

 

代碼隔離vs快速執行

如果你想要一個測試的結果不影響另一個,每個測試在開始運行的階段,都需要創建測試的全專題,返回後又要恢復運行之前的狀態。可是,設置狀態需要的時間很長(如,連接到數據庫,用真實數據初始化到一個已知狀態)

 

PHPUnit解決這個問題的辦法是採用PHP作爲測試語言。有時,全功能的PHP對於書寫短小的,直接的測試是過於強大了,不過,我們利用的程序員已經有使用PHP的全部經驗。因爲我們需要說服勉強的測試人員,降低書寫這些初始測試的門檻是及其重要的。

 

--------------------------------------------------------------------------------------------------------------------

原文:

Chapter 3. PHPUnit's Goals

So far, we only have two tests for the Array built-in and the sizeof( ) function. When we start to test the numerous array_*( ) functions PHP offers, we will need to write a test for each of them. We could write all these tests from scratch. However, it is much better to write a testing infrastructure once and then write only the unique parts of each test. PHPUnit is such an infrastructure.

 

Example 5 shows how we have to rewrite our two tests from Example 4 so that we can use them with PHPUnit.

 

Example 5. Testing Array and sizeof( ) with PHPUnit

<?php

require_once 'PHPUnit2/Framework/TestCase.php';

 

class ArrayTest extends PHPUnit2_Framework_TestCase {

  public function testNewArrayIsEmpty( ) {

    // Create the Array fixture.

    $fixture = Array( );

 

    // Assert that the size of the Array fixture is 0.

    $this->assertEquals(0, sizeof($fixture));

  }

  public function testArrayContainsAnElement( ) {

    // Create the Array fixture.   

       $fixture = Array( );

 

    // Add an element to the Array fixture.   

       $fixture[] = 'Element';

 

       // Assert that the size of the Array fixture is 1.

       $this->assertEquals(1, sizeof($fixture));

  }

}

?>

 

 

 

Example 5 shows the basic steps for writing tests with PHPUnit:

 

The tests for a class Class go into a class ClassTest.

 

ClassTest inherits (most of the time) from PHPUnit2_ Framework_TestCase.

 

The tests are public methods that expect no parameters and are named test*.

 

Inside the test methods, assertion methods such as assertEquals( ) (see Table 6) are used to assert that an actual value matches an expected value.

 

A framework such as PHPUnit has to resolve a set of constraints, some of which seem to conflict with each other. Simultaneously, tests should be:

 

 

 

Easy to learn to write.

 

Tests should be easy to learn to write; otherwise, developers will not learn to write them.

 

 

 

Easy to write.

 

Tests should be easy to write; otherwise, developers will not write them.

 

 

 

Easy to read.

 

Test code should contain no extraneous overhead so that the test itself does not get lost in the noise that surrounds it.

 

 

 

Easy to execute.

 

Tests should run at the touch of a button and present their results in a clear and unambiguous format.

 

 

 

Quick to execute.

 

Tests should run fast so they can be run hundreds or thousands of times a day.

 

 

 

Isolated.

 

Tests should not affect each other. If the order in which the tests are run changes, the results of the tests should not change.

 

 

 

Composable.

 

We should be able to run any number or combination of tests together. This is a corollary of isolation.

 

There are two main clashes within this group of constraints:

 

 

 

Easy to learn to write versus easy to write.

 

Tests do not generally require all the flexibility of a programming language. Many testing tools provide their own scripting language that includes only the minimum necessary features for writing tests. The resulting tests are easy to read and write because they have no noise to distract you from the content of the tests. However, learning yet another programming language and set of programming tools is inconvenient and clutters the mind.

 

 

 

Isolated versus quick to execute.

 

If you want the results of one test not to affect the results of another test, each test should create the full state of the testing before it begins to execute, and return the world to its original state when it finishes. However, setting it up can take a long time (e.g., connecting to a database and initializing it to a known state using realistic data).

 

PHPUnit attempts to resolve these conflicts by using PHP as the testing language. Sometimes the full power of PHP is overkill for writing short, straight-line tests, but by using PHP, we leverage all the experience and tools programmers already have in place. Because we are trying to convince reluctant testers, lowering the barrier to writing those initial tests is particularly important.

 

PHPUnit errs on the side of isolation over quick execution. Isolated tests are valuable because they provide high-quality feedback. You do not get a report with a bunch of test failures that were really caused because one test at the beginning of the suite failed and left the world messed up for the rest of the tests. This orientation toward isolated tests encourages designs with a large number of simple objects. Each object can be tested quickly in isolation. The result is better designs and faster tests.

 

PHPUnit assumes that most tests succeed, and it is not worth reporting the details of successful tests. When a test fails, that fact is worth noting and reporting. The vast majority of tests should succeed and are not worth commenting on, except to count the number of tests that run. This is an assumption that is really built into the reporting classes and not into the core of PHPUnit. When the results of a test run are reported, you see how many tests were executed, but you only see details for those that failed.

 

Tests are expected to be fine-grained, testing one aspect of one object. Hence, the first time a test fails, execution of the test halts, and PHPUnit reports the failure. It is an art to test by running many small tests. Fine-grained tests improve the overall design of the system.

 

When you test an object with PHPUnit, you do so only through the object's public interface. Testing based only on publicly visible behavior encourages you to confront and solve difficult design problems before the results of poor design can affect large parts of the system.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章