Getting started with phpUnit TDD

Source: Internet
Author: User
: This article describes how to use phpUnit to get started with TDD. For more information about PHP tutorials, see.

Use phpunit to practice TDD series

Starting from a bank account

Suppose you have installed phpunit.

We started to understand the idea of TDD (Test-Driven-Development) from a simple example of a bank account.

Create two directories under the Project Directory,srcAndtest, InsrcCreate a fileBankAccount.php, IntestCreate a file under the DirectoryBankAccountTest.php.

According to TDD, we first write tests and then the production code. thereforeBankAccount.phpLeave it blank. let's write it first.BankAccountTest.php.


  

Now let's run it and see the result. The command line for running phpunit is as follows:

phpunit --bootstrap src/BankAccount.php test/BankAccountTest.php

--bootstrap src/BankAccount.phpYes. load the test code before running it.src/BankAccount.phpThe test code to run istest/BankAccountTest.php.

If no specific test file is specified, only the directory is provided, and phpunit will run all the file names under the Directory to match*Test.php. BecausetestOnlyBankAccountTest.phpOne file, so execute

phpunit --bootstrap src/BankAccount.php test

The results are the same.

There was 1 failure:1) WarningNo tests found in class "BankAccountTest".FAILURES!Tests: 1, Assertions: 0, Failures: 1.

A warning error occurs because there is no test.

Account instantiation

Next we will add a test. Note that TDD is a design method that helps you design the functions of a module from the bottom up. When writing a test, we need to start from the user's perspective. If you useBankAccountClass. what should he do first? You must create a new BankAccount instance. So our first test isInstantiation.

public function testNewAccount(){    $account1 = new BankAccount();}

Failed to run phpunit.

PHP Fatal error:  Class 'BankAccount' not found in /home/wuchen/projects/jolly-code-snippets/php/phpunit/test/BankAccountTest.php on line 5

NoBankAccountClass definition, we need to write the production code below. Make the test pass. Insrc/BankAccount.php(Hereinafter referred to as the source file), enter the following content:


  

Run phpunit and pass the test.

OK (1 test, 0 assertions)

Next, we need to add a test to make the test fail. If you create an account, the account balance should be 0. So we addedassertStatement:

public function testNewAccount(){    $account1 = new BankAccount();    $this->assertEquals(0, $account1->value());}

Note:value()YesBankAccountOf course, this function has not been defined. as a user, we hopeBankAccountProvide this function.

Run phpunit. The result is as follows:

PHP Fatal error:  Call to undefined method BankAccount::value() in /home/wuchen/projects/jolly-code-snippets/php/phpunit/test/BankAccountTest.php on line 6

The result tells usBankAccountNovalue()This member function. Add production code:

class BankAccount {    public function value(){        return 0;    }}

Why do you wantvalue()Directly return 0 because the test code requiresvalue()Returns 0. The principle of TDD is to just let the test pass without writing redundant production code.

Account access

After phpunit is passed, let's assume thatBankAccountThe instantiation of has met the requirements. Next, how do you want to useBankAccountWhat about it? I want to save money in it.BankAccountThere is a deposit function. by calling this function, you can increase the account balance. So we added the next Test.

public function testDeposit(){    $account = new BankAccount();    $account->deposit(10);    $this->assertEquals(10, $account->value());}

The initial balance of the account is 0. if we store 10 yuan in it, the account balance should be 10. Run phpunit and test failed because the deposit function is not defined yet:

.PHP Fatal error:  Call to undefined method BankAccount::deposit() in /home/wuchen/projects/jolly-code-snippets/php/phpunit/test/BankAccountTest.php on line 11

Add the deposit function to the source file:

public function deposit($ammount) {}

Run phpunit again and get the following results:

1) BankAccountTest::testDepositFailed asserting that 0 matches expected 10.

At this time, because the deposit function does not operate on the account balance, the initial balance value is 0, and after the deposit function is executed, it is still 0, not the expected behavior. We should increase the user's deposit value to the balance.

In order to operate the balance, the balance should be a member variable of the BankAccount. This variable cannot be changed by the outside world. Therefore, it is defined as a private variable. Next we add private variables to the Production Code$value, ThenvalueFunction should return$value.

class BankAccount {    private $value;        public function value(){        return $this->value;    }    public function deposit($ammount) {        $this->value = 10;    }}

Run phpunit and pass the test. Next, we thought, what else do users need? Yes. get the money. This value is deducted from your account balance when you withdraw the money. IfdepositIf the function passes a negative number, it is equivalent to taking the money.
So we are testing the codetestDepositAdd two lines of code to the function.

$account->deposit(-5);$this->assertEquals(5, $account->value());

Run phpunit again and the test fails.

1) BankAccountTest::testDepositFailed asserting that 10 matches expected 5.

In this case, in the production code, we simply put$valueSet the result to 10. Improve production code.

public function deposit($ammount) {    $this->value += $ammount;}

Run phpunit again and pass the test.

New constructor

Next, I think that users may need a different constructor.BankAccountObject, you can input a value as the account balance. So wetestNewAccountAdd a test for this instantiation.

public function testNewAccount(){    $account1 = new BankAccount();    $this->assertEquals(0, $account1->value());    $account2 = new BankAccount(10);    $this->assertEquals(10, $account2->value());}

Run phpunit and the result is:

1) BankAccountTest::testNewAccountFailed asserting that null matches expected 10.

This is becauseBankAccountNo constructor with parameters. thereforenew BankAccount(10)Returns an empty object.value()The function returns null. To pass the test, we add a constructor with parameters in the production code.

public function __construct($n){    $this->value = $n;}

Run the test again:

1) BankAccountTest::testNewAccountMissing argument 1 for BankAccount::__construct(), called in /home/wuchen/projects/jolly-code-snippets/php/phpunit/test/BankAccountTest.php on line 5 and defined/home/wuchen/projects/jolly-code-snippets/php/phpunit/src/BankAccount.php:5/home/wuchen/projects/jolly-code-snippets/php/phpunit/test/BankAccountTest.php:52) BankAccountTest::testDepositMissing argument 1 for BankAccount::__construct(), called in /home/wuchen/projects/jolly-code-snippets/php/phpunit/test/BankAccountTest.php on line 12 and defined/home/wuchen/projects/jolly-code-snippets/php/phpunit/src/BankAccount.php:5/home/wuchen/projects/jolly-code-snippets/php/phpunit/test/BankAccountTest.php:12

Two callsnew BankAccount()Errors are reported, and constructors with parameters are added. constructors without parameters cannot work. Slavec++/javaStudents in the transition will immediately consider adding a default constructor:

public function __construct() {    $this->value = 0;}

But this does not work. because php does not support function overloading, there cannot be multiple constructors.

What should I do? By the way, we can add the default value for the parameter. Modify the constructor:

public function __construct($n = 0){    $this->value = $n;}

This callnew BankAccount()0 is passed to the constructor to meet the requirements.
Phpunit: run the following command. the test is successful.

In this case, our production code is:


  value = $n;    }        public function value(){        return $this->value;    }    public function deposit($ammount) {        $this->value += $ammount;    }}?>

Summary

Although we do not have much code, we are confident in every step. this is the benefit of TDD. Even if you are not very confident about the php syntax (such as me), you can also have confidence in your code.

Another advantage of using TDD to write a program is that you do not need to carefully design a single module before coding. you can design it during write testing. The modules developed in this way can meet user needs and are not redundant.

More phpunit functions will be introduced later.

The above describes how to use phpUnit to get started with TDD, including some content, and hope to help those who are interested in PHP tutorials.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.