Application of test driver development in PHP

zhaozj2021-02-16  87

This article has been adopted by Chengdu Computing Institute "Computer Application", copyright belongs to all the public and the authors, and is not true for other articles published online. Do not reprint.

TDD

Test drive development (TDD) is a software development method in recent years. As a best practice, test drive development plays an important role in the XP method. Its significant improvement in development efficiency and code robustness has been confirmed by more and more instance projects.

The main spirit of TDD can be summarized as "test first, fast feedback". Before you have a practical function code, you will start writing test code, reflect the design by testing, making the test code a de facto design document. At the beginning, the test code can even be compiled because the function code to be tested has not been written. We have passed the test as soon as possible by writing a functional code that is just enough, and there is no extra function. Then add the test to make it unexpected, and then the need to produce the encoding. Reconstruct the code after a certain function is completed, then add new features. This continues to quickly "Rad / Green / Refactor" loop, to test the coding requirements, step by step, generate simple and easy to understand, test, strong robust, just enough to use no excessive function Excellent code, forming the development model of test drivers.

2. PHP TDD

The nature of TDD is a software engineering development method, which should not be dependent from the specific language environment. However, its specific application conditions in different languages ​​are different. From a language point of view, test driver development originated from object-oriented SmallTalk communities, forming in Java language. The launch of the Juni Automation Unit Test Framework JUnit is marked, and TDD jumps out the theory and experiment, and it is widely used in practice. The XUnit family derived from JUnit becomes an indispensable tool in TDD applications, making TDDs possible in many languages. The phpUnit [Note 1] used in this paper is one of them.

TDD has a strong Oo color from the beginning of birth. In Java / C , etc., in order to separately isolate a given module (unit test), Iso technology such as a polymorphic interface is used to implement isolation.

Dr. Robert Koss and Jeff Lanr in the article on CUJ, discussed the method of practicing TDD with CUJ, using macro to implement automation test, using macro to implement automation test, link-time) Polymorphism to achieve isolation.

For the implementation of TDD, PHP has its own language characteristics. First, the PHP support class can be said to be part OO. Also because this phpUnit is likely to imitate the structure of JUnit. The support for OO in PHP5 has considerable improvement and expansion. However, PHP is not born to OO, it takes care of C's color. And in the current situation of domestic PHP projects, OOD / OOP is not dominant. In a wide range of stable versions php4.x, OO supports simple inheritance, but because of weak type characteristics, there is no polymorphism. At present, there are many Java environments based on the Java environment. Therefore, it is necessary to discuss some discussions.

3. Example

We use the PHP standard function exPlode () to implement another standard function strTok () [Note 2] as an example, specifically, how to apply TDD in the PHP project. To distinguish between standard functions, we are named Strtk () to be implemented. Operating environment Apache

1.3.23

, PHP 4.1.1, phpUnit 0.6.2.

3.1 Task Analysis - Demand, Design, Test

The programmer passes two strings parameters to strtk (), and the SEP will be called STRTK ($ SEP), and will receive each non-fry string divided by the $ SEP in the $ SEP. In fact, TDD does not advocate a detailed design provision or forming a bureaucratic design document, because "test reflection design", the test is the encoded design document, and the increasing test corresponds to the changing demand. Any time in demand changes Our code is available because they are guaranteed to pass. This is consistent with the spirit of the XP method "active hug". 3.2 First Wheel - PHPUNIT, Pseudo Realization Model

First, think of easy testing is the case where there is no partition $ SEP in the $ STR, and the result should be the original string $ STR. We start writing the first method in test cases:

// Test for strtk () Require_once "phpUnit.php"; // Using phpUnit request_once "strak.php"; // The file is located in the file

// A test case is a subclass of PHPUNIT_TESTCASE inherits the subclass test_strtk extends phpUnit_testcase {// constructor function test_strtk ($ testname) {// Call the parent class constructor to perform a test method called $ testname $ this-> PHPUNIT_TESTCASE ($ testName);} // initialization function setup () {// This function will be called before each test method is called} // Depose function teardown () {// After each test method is executed, this function will Call} // First test method: no match characters, should return to the original string function test_no_match () {$ Teststr = "Abcd"; $ RSLT = STRTK ($ Teststr, "#"); $ this-> assertequals $ Teststr, $ RSLT, "No Matching Brand");}}

// Perform each name in the specified test case class with 'test', the test result is output when the test result is output, so the method is named "_ '$ tsstrtk = new phpUnit_testsuite (Test_Strtk); $ TESTRSLT = PhpUnit :: run ($ tsstrtk); // Perform a result Echo $ test-> tohtml (); // Output in the browser?>

Saved as Test_STRTK.php, execute results:

FATAL ERROR: FAILED OPENING Required 'strtk.php'

Among the expectations, because the files and functions to be tested have not existed. Now test require us to create files strtk.php and write function strtk ():

//strtk.php Function Strtk ($ STR, $ SEP) {RETURN $ STR; / / fake-it pattern}?>

Execute Test_STRTK.PHP, the test passes:

Testcase test_strtk-> test_no_match () passed

In TDD, the most important thing is to pass the test as soon as possible. It seems to be inevitious, but it is indeed a method that passes the fastest pass. This is in line with the "Fake-IT Pattern" in TDD. Pseudo-realization will be replaced by the increase in tests. But why not directly replenish the code to return "ABCD"? Because returning $ STR This obvious abstraction does not cost us more time than hard coding. When the abstraction is not so easy, we have the following methods to use the test drive abstraction and ensure the correctness of the abstraction. 3.3 Second Wheel - Triangle Mode Calls once strtk () should be able to obtain the first substring of the split. We add test methods in Test_STRTK classes:

// Get the first substring

Function test_get_first_substr ()

{

$ teststr = "one, two, three";

$ RSLT = STRTK ($ TESTSTSTR, ",");

$ this-> Assertequals ("One", $ RSLT, "Failed to get the first substring");

// Triangulate Pattern

$ teststr = "feb./8/2004";

$ RSLT = STRTK ($ TESTSTR, "/");

$ this-> assertequals ("feb.", $ RSLT, "Failed to get the first substring");

}

Run the test, and the result of the expected failure:

Testcase test_strtk-> test_no_match () passed

Testcase test_strtk-> test_get_first_substr () failed: Failed to get the first substring Expected One, Actual One, Two, Three

Testcase test_strtk-> Test_get_first_substr () failed: Failed to get the first substring expected feb., actual feb./8/2004

The original serial is directly returned. You can also prove that try hard coding to return "one" or "feb." by test practice. There are two assertions in this test method, and the "Triangulate Pattern" is used to make further abstract needs. Test requirements We use the exPlode () function:

Function Strtk ($ STR, $ SEP)

{

$ strarr = evdE ($ SEP, $ STR);

Return $ strarr [0];

}

Hard coding 0 gets the first substring, just enable the test.

3.4 Third Wheel - Sub Test Mode, Reconstructing Next, you should access the subsequent substrs by continuous calling string, ie attempt to add such a test and pass:

// Get a subsequent string

Function Test_Get_Followup_Substrs ()

{

$ teststr = "one / two / three / four / five";

$ RSLT [0] = STRTK ($ TESTSTSTR, "/");

$ RSLT [1] = strtk ("/");

$ RSLT [2] = strtk ("/");

$ RSLT [3] = Strtk ("/");

$ this-> Assertequals (Array ("One", "Two", "Three", "FOUR"), $ RSLT,

"Failed to get a subsequent string");

UNSET ($ RSLT);

$ teststr = "to be, or not to be";

$ RSLT [0] = Strtk ($ Teststr, ""); $ RSLT [1] = Strtk ("");

$ RSLT [2] = strtk ("");

$ this-> assertequals (array ("to", "be,", "or"), $ rLT, "fail to get a subsequent string");

}

If there is no quick test, this test span is too large. "Quick feedback" in TDD is very important. We may wish to add this test first, divide the demand reflected into several relatively simple needs to write tests separately. This is in line with the "Child Test Pattern".

a. With the optional needs of the parameters, it seems to write the function-specific reference to Strtk ($ STR, $ SEP = NULL).

b. With the need to keep the original skeleton state, this requires $ strarr in the function to static arrays.

c. There is a need for a sense of perceived function, which also requires a static variable within the function to record.

d. You can start a new round of segmentation by transmitting two parameters again.

By writing these sub-tests and passes, we finally got the code to test Test_Get_Followup_substrs ():

Function Strtk ($ STR, $ SEP = NULL)

{

Static $ strarr; // substring array

Static $ i = 0; // Function call number

IF (IS_NULL ($ SEP))

{

// Get a subsequent string

Return $ strarr [$ I ];

}

Else

{

// Start a new split

$ strarr = evdE ($ SEP, $ STR);

$ I = 0;

Return $ strarr [$ I ];

}

}

The code has repeated part of Return $ strarr [$ I ], indicating that it should be refactored:

Function Strtk ($ STR, $ SEP = NULL)

{

Static $ strarr;

STATIC $ I = 0;

IF (! is_null ($ SEP))

{

$ strarr = evdE ($ SEP, $ STR);

$ I = 0;

}

Return $ strarr [$ I ];

}

All of the tests were still passed, indicating that reconstruction is correct.

3.5 Subsequent works to this, our code is already qualified, but there are still many jobs to achieve you can use:

a. Nothing to do any parameter security: how to pass on the air, explicitly specify how NULL. [Note 3]

b. Boundary conditions definitions are not allowed: If the original string has ended, there will be a consequence of two separators. [Note 4]

c. Differentiation of separator $ SEP: $ SEP is more than one character is handled, and the $ SEP incorporated during the split process is inconsistent. [Note 5]

These requirements can be expressed by testing to solve with the front similar approach.

4. Conclusion We can see that when writing tests with phpUnit, using Junit in Java is similar, it is a test framework built by class and method; and the simple file that implements isolation is used, this and C is connected. The state is similar. The limited OO characteristics of PHP and the execution of the script make the hybrid feature in which TDD has such a semi-object / semi-process therein.

Compared to other languages, the weak type of PHP makes more detailed test design when using them to perform TDD practices, including type checks. Because of this, the development of PHP projects requires powerful protection of TDD to better play the power of this flexible and trap.

Note note

Note 1. Can be downloaded by http://pear.php.net/package/phpunit. The latest version is 1.0.0 alpha3, which requires PHP5 / Zend Engine 2.

0.6.2

It is the last version that can be used on PHP4 stability. Note 2. For example, this is fictitic with STRTOK () encapsulation expLode (). By reading the actual PHP implementation source, you can know that both are parallel, without the relationship between the mutual packages. These two functions are still very concise, without the need to use a regular expression (Regular Expression). Note 3. Continue with the optional reference to match the IS_NULL () judgment will cause confusion. To resolve the functions that should be introduced into FUNC_NUM_ARGS () and FUNC_GET_ARG (). It is worth noting that exPlode () in PHP4 is not allowed to be emandably or null, otherwise lead Warning and returns false, the source string can be empty. STRTOK () is just the opposite, the separator can be null, and the source is longer to return false. Note 4. The original string ends back NULL, and two consecutive separators return the air string. The programmer is unable to distinguish between the two cases only by the return value of the serial or Boolean value. Trying to traverse all substrings will have potential vulnerabilities with while (strlen (strlen ("" / "))). In fact, the Strtok () in PHP4 returns false when the source string ends, and two split points are slightly separated and returned to the next sub-string. Note 5. Standard Functions STRTOK () allows the receiving string of multi-character, each of which is a separator, respectively, respectively, the entire string as a separator. STRTOK () continues from the current location when the separator change changes from the current location.

references:

[1] Kent Beck. Test-Driven Development: by Example [M]. Addison Wesley. Nov. 2002 [2] Martin Fowler, Kent Beck, John Brant, William Opdyke, Don Roberts. Refactoring: Improving The Design Of EXISTING CODE M]. 1999 [3] Dr. Robert S. Koss, Jeff LANGR. Test Driven Development In C / C . C / C Users Journal [J]. Oct. 2002

转载请注明原文地址:https://www.9cbs.com/read-12086.html

New Post(0)