I have a legacy PHP site that is up and running,
We are required to make modifications, and the original programmers are long gone, they left behind a purely procedural PHP code with no unit tests whatsoever.
Is there a way to automatically generate unit tests from the production web site?
No, there is no way to generate sensical unit tests from the production site.
How would such a test generator know what rewrite rules you have configured in your web server to even hit code on disk? Even if it knew that or there were no rewrite rules, how would this test generator know how to generate code for a reasonable number of paths? I've seen some scripts that make the assumption of a request always getting the same result and throwing an exception if they don't, but that isn't a good thorough test, and it doesn't even apply in all cases.
Besides, if your code is purely procedural, good unit testing becomes difficult.
Related
We have a project developed by 2 years with poorly designed architecture. Now a days there are no any unit tests at all.
Current version of system works satisfyingly but we vitally need refactoring of core modules.
The budget is also limited so we can not hire suffisient number of developers to write unit tests.
Is it the possible strategy to generate code automatically for unit tests which covers, for example, interaction with data, in assumpion that now system works fine and current system's output can be converted in XML-fixtures for unit testing?
This approach gives us a possibility to quickly start refactoring of existing code and receieve immediate feedback if some core functionality is corrupted because of changes.
I would be wary of any tools that claim to be able to automatically determine and encode an arbitrary application's requirements into nice unit tests.
Instead, I would spend a little time setting up at least some high-level functional tests. These might be in code, using the full stack to load a predefined set of inputs and checking against known results, for instance. Or perhaps even higher-level with an automation tool like Selenium or FitNesse (depending on what type of app you're building). Focus on testing the most important pieces of your system first, since time is always limited.
Moving forward, I'd recommend getting a copy of Michael Feathers' Working Effectively with Legacy Code, which deals with exactly the problem you face: needing to make updates to a large, untested codebase while making sure you don't break existing functionality in the process.
I'm currently developing a simple framework for PHP that manages and dispatches ajax calls. One of its features is that it automatically takes care of sending the appropriate headers depending on what is happening in the backend. During the past couple of days I've started writing a lot of unit tests for PHPUnit and I'm trying to get a decent code coverage. (Yes, high code coverage by itself doesn't really mean anything, I know. But it still is a good indicator.)
However, because it is (to my knowledge) not possible to send/check headers when PHP is in CLI mode, a lot of tests need to be run through a local webserver. This allows me to easily check the headers and the response body. Unfortunately, the code executed during these tests is, naturally, not tracked by PHPUnit. (Just to be clear: every piece of code that can be checked locally, is checked locally. But everything that is related to headers does not fall into that category.)
I know that I can encapsulate the header() call and replace it during testing with a mock object. However, then I'd have to re-implement the entire logic of header replacement and what not with all its potential quirks and bugs, so I'd essentially be testing my own header()-implementation instead of what's really happening - which is precisely what I don't want to do.
So I guess my question is this: can I, somehow, include those "remote calls" in my code coverage report? Or do I (and that's my guess) simply have to accept the fact that I've to miss out on 100% code coverage in order to test under real-world conditions?
Well, in practice it's practically impossible to get 100% coverage for an entire code base. Where you really want 100% is in the core of the application (The libraries and reused components). The rest is very good to test, but if you'll find there are situations that make it quite difficult to test, so don't stress yourself over a few lines of code that are untestable.
As far as your specific problem, I wouldn't even be writing unit tests for that sort of thing. What I would write are UI tests using Selenium HQ. It's still fully automated, and runs from within PHPUnit, but it uses one or more browsers. It's really more of an integration or acceptance test than a Unit test, but it works quite well...
Apparently, there is no way to do it.
While ircmaxell's answer was interesting, it didn't really answer my question (hence I marked this answer as accepted).
I'm in charge of at least one large body of existing PHP code, that desperately needs tests, and as well I need some method of checking the production site for errors.
I've been working with PHP for many years, but am unfortunately new to testing. (Sorry!).
While writing tests for code that has predictable outcomes seems easy enough, I'm having trouble wrapping my head around just how I can test the live site, to ensure proper output.
I know that in a test environment, I could set up the database in a known state... but are there proper methods or techniques for testing a live site? Where should I begin?
[I am aware of PHPUnit and SimpleTest, but haven't chosen one over the other yet]
Unit testing frameworks like PHPUnit are built more for testing the functionality of separate, logical units (i.e. classes), not so much the behaviour of entire live sites. One household name for that is Selenium, a web application testing system. It is my understanding that Selenium tests can in turn be integrated with PHPUnit.
As for the choice between Simpletest and PHPUnit, check out my recent question about PHPUnit vs. SimpleTest - the answers to that question, notably #Gordon's, managed to convince me of PHPUnit.
I second Pekka's suggestion. Also, I strongly suggest using PHPUnit, as it is the de-facto Standard in UnitTesting frameworks in the PHP World.
Another thing you can do is head over to phpqatools.org (edit: this website is no longer active) and use the given tools to analyze your codebase, find dead code, copy and paste, code violations, etc.
Also profile your code with XDebug or Zend Debugger to find out what it is actually running how often. This way you will not only get an idea of which code you should test first (those that runs most often), but also how it performs, which is a good starting point when you wil optimize it after you have written the Unit-Tests.
In addition, check out:
Legacy Code Nightmare and
Theory and practice – migrating your legacy code
PHPUnit Manual
As a developer that's used to static typing I usually let the compiler tell me if the code is correct, logic flaws excluded of course. But when refactoring PHP I find it is VERY hard to know that my code is correct.
There always seem to be some lingering reference to some method or member somewhere that get's broken and doesn't show up until runtime. Even when using the limited refactoring support in Zend Studio things tend to get broken somehow.
Due to the dynamic nature of the language itself, I understand it is a hard problem. But are there any tools out there to statically verify PHP code so that I know that it is okay before runtime? I don't want to see any more "Undefined property" error messages.
Write tests for your code (http://www.phpunit.de/), setup a continuous integration server, run UI tests (http://pear.php.net/package/Testing_Selenium/). With enough testing, you will find your problems straight after you commit bad code. Just keep the test code coverage high.
That's one of the main points of unit tests - you can refactor your code without actually breaking it, because you check all functionality after every change.
I would recommend #viraptor's solution for preventing your current problems.
Here is some information on Static Analysis and Refactoring in PHP.
Static Analysis
http://strategoxt.org/PHP/PhpSat
PHP Refactoring
Tools for PHP code refactoring
unit tests. i'm the author of Testilence
My workplace consists of a lot of cowboy coders. Many of them are junior. Which coincidentally contributes to a lot of code quality issues.
I'm looking for suggestions on how to best wane my team into using TDD (we can start with Unit tests, and move into regression tests, and later more automated testing).
Ultimately, I want us to learn more quickly from our mistakes, and produce better code and breed better developers.
I'm hoping there are some practical suggestions for how to introduce TDD to a team. Specifically, what tools are best to choose in the LAMP (php) stack.
Sorry if this question is too open-ended.
After going through this process four times now, I've found that any introduction of TDD will fail without some level of enforcement. Programmers do not want to switch style and will not write their first unit test and suddenly see the light.
You can enforce on a management level, but this is time-consuming for all involved. Some level of this is necessary at the beginning anyway, but ultimately you will need automatic enforcement. The answer to this is to introduce Continuous Integration.
I've found that a CI Server is the ultimate keystone to any TDD environment. Unless developers know that something bad will happen if they don't write the tests, you'll always have cowboys who feel it's beneath them.
Make writing tests easy and the results visible.
Use a TestFramework with good documentation. like SimpleTest
If test depend on database contents, create a reference database that will be dropped and created at the beginning of a script.
Make a script that runs all test and shows the results on a standalone monitor or something that will make the test visible / easily accessable. (Running a command prompt is not an option)
I personally don't write test for every chunk of code in the application.
Focus on the domain objects in the application. In my case these are "price-calculation" and "inventory-changes"
Remind them that they are probably already writing tests, but that they delete their work just after creation.
Example: During the development of a function you'll have a page/testscript in with an echo or var_dump() the result. After a manual validation of the result you'll modify the parameters of the function and check again.
With some extra effort these tests could be automated in a UnitTest. And which programmer doesn't like to automate stuff?
As for the team question as well as universal ideas about software development and testing, I would suggest Joel Spolski's website and books: http://joelonsoftware.com/ I got many insights from him.
SimpleTest - excellent documentation and explanations of testing for php
Another way to start TDD is try to use PHP framework. Without framework, it's hard to implement unit test effectively.