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
Related
I have some PHP code that is does not have good test coverage and is not easily testable in its current state. If I use commands from the refactor menu of PhpStorm, and make no other changes, how sure can I be that this won't change the behaviour of my application?
How safe are other automatic refactoring tools?
My understanding is that these tools will apply static analysis and could only cause changes to behaviour if the application does something very weird like depending on the output of debug_backtrace()
The (overly) simple answer is it's no better or worse than manually refactoring.
If you have good tests then it's safe. If you don't then it's not.
I would say do not do any refactoring without having unit tests for each function being refactored. Refactoring should not break unit tests, if it does then you haven't refactored it, you've changed it.
I have been bitten by PhpStorms refactoring tools in weird ways in the past, even resulting in broken syntax. But, that was a long time ago, the tools have moved on, and it's always easy to go back a step if you're methodically committing changes to your SCM.
Today I am faced with a spaghetti of some new unknown code for a webservice, and I need to make sense of it. The code is using CodeIgniter with a HMVC extension which helps, but the problem is that it contains many unused/old/etc... files/folders. It also does not help that I recently converted to using PHP, so I am still learning my way around best practices.
Is there a way to set the debugger up in a way that it breaks at the beginning of every single PHP file? (I have Xdebug set up ready to rock)
What is the most effective way to analyse code for unused files? ( I saw a few projects for this, but unsure where to start)
Thanks!
As per the discussion in the comments, I'd wondered if the execution coverage tools in XDebug would help here. This is a low-level code monitor that watches what lines of PHP code have been executed when you start a program. As you'd expect, this adds a certain level of overhead, so it is generally not added to live environments.
Hosted build systems like Travis and Scrutinizer do code coverage reporting, though they probably rely on tools like PHPUnit and XDebug to actually make them work.
Is there a good way to test if a PHP project works well with a new version of PHP?
Lets say we have a project developed under PHP 5.0 and want to run it now with PHP 5.4. The project have no unit tests or something like that.
Just run it with PHP 5.4 and click around to see if there are errors is not save enough.
Run your tests. If you don't have tests, write some now under PHP 5.0. Then run them under 5.4. If they break, then you've found something that needs to be fixed. Having a suite of test scripts is good practice anyway so if you haven't got any, this is a good opportunity to start writing them. Look up phpUnit, which is the most common PHP tool for writing unit tests.
For creating a test suite on an existing project, I recommend using a tool like Selenium or Sahi which can record a browser session. Turn on the recording and start testing as normal. Voila: One repeatable test. You're going to have to do this kind of testing anyway, so you may as well record them. Granted, those are functional tests, rather than unit tests, but they are tests all the same, and if you can cover enough of your functionality with them then you'll have a fairly comprehensive demonstration that the system is working.
Syntax check: Use PHP's command-line -l option in a batch job to run a syntax check on all your files. This will prove that everything parses successfully.
That will eliminate the obvious problems.
Use a decent IDE to develop your code in. IDEs like Netbeans will highlight syntax issues and warning for you and underline the relevant code. This makes finding bugs much much easier.
If you're still developing in Notepad, you're missing out on a whole world of good stuff.
If you're using ereg() or related functions, they need to change to preg_match() etc. You can get away with still using mysql_query() for DB access, since that's only deprecated in 5.5, but if you're using it you may as well consider this to be a good time to make that change too.
Look up the Migration Guides provided by PHP. These give full details of all the code-breaking changes between PHP versions. In particular, pay attention to the deprecated features.
The most significant version for this was 5.3: A lot of old code was broken by the features which were deprected in 5.3. These were features like magic_quotes and register_globals; they had been considered bad practice for a very long time before that, but it took them until 5.3 to actually deprecate them. If you're using them, this will be the biggest problem you'll have to face.
Tools like PHPMD and PHPCodeSniffer, PHP Lint may help to analyse your code. They aren't really designed for version compatiblity checking, but may help you find issues.
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