Bastian's Blog ~~~~~~~~~~~~~~ :Author: lapis :Date: Mon, 07 Feb 2011 00:30:49 +0100 :Revision: 2 :Copyright: CC by-nc-sa ====================================== PHPUnit - Some lesser known assertions ====================================== :Keywords: Tools, PHP, PHPUnit, testing, Unittests, assertion, annotation, unittest, software, development, continous integration, :Description: :Abstract: As I am a bit obsessed with testing and unit testing in particular. As I am also a trainer I am trying to watch people on how they do solve different problems in their daily work. Doing this I recognized that almost everyone does not read any documentation nor has the drive to know more about the tools he is using, and stays in his boundaries of knowleadge until someone hits his nose against other possibilities. This is kind of the article is about - getting to know PHPUnit a bit more and be aware of it's nice and problem solving features. It just came into my mind: Could this be part one of a series? Probably. Let's see how it turns out. As I already pointed out in the abstract, people often do not know their tools. Even or because they are using them each and every day and do get caught in the same old pace they do everytime. I think it's time to change that. For today let's focus on some Assertions which make my life much easier writing unit tests. Assertions ========== In general an assertion is an expectation of the developer on what your `system under test`_ (SUT) will return and how it will react in different situations. As of the part of unit testing an assertion is e.g. the content of a variable, the return value of the tested method. As you can imagine there are infinited ways to verify this behavior and PHPUnit_ comes with a handy number of assertion to help you being successful in this task. .. _system under test: http://en.wikipedia.org/wiki/System_under_test .. _PHPUnit: http://phpun.it Ok let's be honest, in every case we always do the boring comparison between a returned and an expected value. But insstead of always using the same old **assertEquals()** we are going to explore some more special assertions. So, let's start with a set of string comparison methods. XML to the rescue ----------------- In many places XML is used to communicate and exchange data e.g. between to machines by using webservices. To verify that the returned value of the method is as expected, PHPUnit provides several assertions to do this: * assertXmlStringEqualsXmlString() * assertXmlStringEqualsXmlFile() * assertXmlFileEqualsXmlString() * assertXmlFileEqualsXmlFile() * assertEqualsXMLSructure() Meanwhile the first 4 methods rely on the equal structure and nodevalues the last one (assertEqualXMLStructure()) only testifies the correctness of the XML structure. This comes in very handy when testing webservices with changing content whithin an integration test. Reading invisible attribute --------------------------- Sometime methods to be tested simple do not return anything, but alter class attributes in any way. This is the time where people start to question the unsability and reliability of (unit) tests. They start building proxy-classes to raise the visibility of these class-attributes (since it is possible to raise the visibility from **protected** to **public**), or even worse change the visibility of the attribute in the production code and simply ignore the benefits of proper set visibilities as in a part of a decent OOP strategy. Here is a releaving message for everyone using these smells in his sources: User one of the assertAttribute*() methods to read a specific protected or private class attribute. Also **readAttribute()** is able to alter the visibility of an attribute to read its value. Negations --------- As you might expect every method I named earlier has also a negative sibling. To gain the reversed assertion just add a **Not** to the method name at the correct position (e.g. AssertAttributeNot*()). So much about some findings I made using PHPUnit extensively in the early past. Let's see I think I will write about Mock- and Proxy-Objects soonish. Trackbacks ========== Comments ======== - PHPGangsta at Sat, 22 Jan 2011 00:24:14 +0100 Date: Mon, 31 Jan 2011 22:24:14 +0100 There are of cause many more unknown or unused assertions. I was very sad when the Performance Extension was removed in 3.4, because with it you were able to measure the time of a function call: http://www.phpunit.de/manual/3.3/en/testcase-extensions.html#testcase-extensions.performance Now you have to implement that on your own with microtime() or other timer scripts if you want to assert the time a function or method runs. - lapistano at Mon, 07 Feb 2011 00:53:38 +0100 hey PHPGaangsta, sure there are a lot more than those XML asserting methods. As I was already thinking about at the beginning of the article I am planning to make this a series. Next up constrains. hf Bastian - Pip Jones at Thu, 24 Mar 2011 02:26:46 +0100 Bastian, I have been reading your presentation on slideshare http://www.slideshare.net/lapistano/debugging-php-with-xdebug-inside-of-eclipse-pdt-21 and I\'m very interested to know if are saying you can get PHPUnit to launch a remote debug session in Eclipse PDT? (Slide 26) I have used your example, replacing the cli php with phpunit (and also sending in the xdebug php.ini settings via the -d parameter), but it just doesn\'t trigger the debug session. Can you confirm it\'s possible to debug a PHPUnit test remotely in Eclipse using the XDebug JIT feature? thanks a lot. Ps. sorry if this is hijacking this post slightly, but it was the closest topic I could find! - Bastian at Thu, 24 Mar 2011 23:32:47 +0100 Hi Pip, it is theoretical and practical possible to run a PHPUnit test within a debugger. Therefore you have to checkout the PHPUnit sources and dependencies from git and import them into your Eclipse workspace. After you enabled the JIT-option within Eclipse, define the cli environment variable. Now run the current test using the current checked out PHPUnit. Eclipse should now asked you to authorize the debugging session. If you set a breakpoint the debugger will halt the execution at this point. So much about how to possibly get it run. But it should not be necessary to debug tests. If this gets feasible the test is potentially lying and not doing what it should. You should consider to refactor your test to the smallest possible unit. Doing so it will be more readable and easier to understand and even faster to execute ;) hope that helped Bastian