As PHP transforms from a simple scripting language into a mature programming language, the complexity of a typical PHP application's code base increases. To control the support and maintenance of these applications, we can use a variety of test tools to automate the process. One is unit testing, which allows you to directly test the correctness of the code you write. However, the usual legacy code base is not suitable for this kind of testing. This article describes refactoring strategies for PHP code that contains common problems to simplify the process of testing with popular unit test tools while reducing the dependency on improved code base. Introduction Review of PHP 15 years of development, we found that it has been from a simple alternative to the popular CGI script of the dynamic scripting language into a mature modern programming language. As the code base grows, manual testing has become an impossible task, large or small, and all changes to the code will have an impact on the entire application. These effects can be as small as affecting the loading or form saving of a page, or it may be a problem that is difficult to detect, or an error that occurs only under certain conditions. Even, it may cause previously fixed issues to re-appear in the application. Many test tools have been developed to solve these problems. One popular approach is the so-called feature or acceptance test, which tests the application through the typical user interaction of the application. This is a good way to test each process in your application, but the testing process can be very slow, and it is generally not possible to test whether the underlying classes and methods work as required. At this point, we need to use another test method, which is unit testing. The goal of unit testing is to test the functionality of the application's underlying code to ensure that they are executed to produce the correct results. In general, these "growing" Web applications slowly emerge with more and more legacy code that is difficult to test over time, making it difficult for development teams to guarantee the coverage of application testing. This is often referred to as "non-testable code." Now let's look at how to identify the non-testable code in the application and how to fix the code. Identify non-testable code the problem domain for which the code base is not testable is usually not obvious when writing code. When writing PHP application code, people tend to write code according to the process of WEB requests, which is often a more procedural approach to application design. Rushing to complete a project or quickly fix an application can prompt developers to "take shortcuts" to quickly complete the coding. Previously, poorly written or confusing code could exacerbate the problem of non-testability in your application, as developers typically make the least-risky fix, even if it may lead to subsequent support issues. These problem domains are not discoverable by normal unit tests. Function global variables that rely on global state are handy in PHP applications. They allow you toInitialize some variables or objects in your program, and then use them elsewhere in your application. However, this flexibility comes at a cost, and the overuse of global variables is a common problem with non-testable code. We can see this in Listing 1. Listing 1. Functions that depend on the global state Results = $dbconn->query (' Select name from MyTable '); } public Function Getfirstresult () {return $this->results[0];}} Here, in order to test the FDFDFD method of the object, we eventually need to establish a database connection, add some records to the table, and then clear all the resources after the test. If testing FDFDFD does not need these things at all, the process can be too complex. Therefore, we want to modify the constructor shown in Listing 6. Listing 6. Classes modified to ignore all unnecessary initialization logic Init (); Public Function init () {$dbconn = new databaseconnection (' localhost ', ' user ', ' password '); $this->results = $dbconn-& Gt;query (' Select name from MyTable '); } public Function Getfirstresult () {return $this->results[0];}} We refactored the bulk of the code in the constructor and moved them into an init () method, which is still called by the constructor by default to avoid breaking the logic of existing code. However, now we can only pass a Boolean value to the constructor during the test to avoid calling the Init () method and all unnecessary initialization logic. This refactoring of the class also improves the code because we separate the initialization logic from the object's constructor. Hard-coded class dependencies as we described in the previous section, a large number of class design issues that are difficult to test are focused on initializing various objects that do not require testing. In the front, we know that heavy initialization logic can be a big burden on the writing of tests (especially when the tests do not need them at all), but if we create them directly in the class methods we test, it can cause another problem. Listing 7 shows the sample code that might be causing the problem. Listing 7. Class that initializes another object directly in one method Query (' Select name from user '); Sort ($results); return $results; }} Let's say we're testing the Getuserlist method above, but our test focus is to ensure that the returned user list is sorted correctly in alphabetical order. In this case, our problem is not whether we can get these records from the database, because we want to test whether we can sort the returned records. The problem is that because we instantiate a database connection object directly in this method, we need to perform all of these tedious operations to be able to complete the test of the method. Therefore, we want to modify the method so that the object can be inserted in the middle, as shown in Listing 8. Listing 8. This class has a method that instantiates another object directly, but also provides an overriding method Query (' Select name from user '); Sort ($results); return $results; You can now pass directly to an object that is compatible with the intended database connection object, and then use the object directly, rather than creating a new object. You can also pass in a mock object, in which we return the value we want in a hard-coded way in some calling methods. Here, we can simulate the database Connection object Query method, so that we just need to return the results, and do not need to really query the database. Such refactoring can also improve this approach, because it allows your application to insert different database connections when needed, instead of just binding a specified default database connection. The benefits of testable code Obviously, writing more testable code can certainly simplify unit testing for PHP applications (as you can see in the example shown in this article), but in the process it can also improve the design, modularity, and stability of your application. We've all seen the "spaghetti" code, which has a lot of business and performance logic in one of the main processes of a PHP application, which undoubtedly poses a serious support problem for those who use the application. In the process of making the code more testable, we refactor some of the previously problematic code, which is not only problematic in design, but also functionally problematic. By making these functions and classes more versatile, and by removing hard-coded dependencies, we make it easier to reuse other parts of the application, and we improve the reusability of the code. In addition, we have replaced code that is poorly written to better-quality code, simplifying future support for the code base. Concluding remarks in this article, we learned how to improve the testability of PHP code through some typical non-testable code examples in the PHP application. We also describe how these situations appear in the application, and then describe how to properly fix these problem codes to facilitate testing. We also learned that the code changes not only improve the testability of the code, but also improve the quality of the code and improve the reusability of the refactoring code.
http://www.bkjia.com/PHPjc/735874.html www.bkjia.com true http://www.bkjia.com/PHPjc/735874.html techarticle as PHP transforms from a simple scripting language into a mature programming language, the complexity of a typical PHP application's code base increases. In order to control these applications ...