AssertNotNull
- Specifications
- Feedback
- Regression
- Granularity
I vloged my thoughts here.
Finally, here's the code I was looking at.
and check out www.approvaltests.com
Pre-JavaOne Hudson Meetup
As we near autumn up here in the Northern Hemisphere, the wind is starting to blow a bit chillier and here in the Bay Area that can only mean one thing: Oracle is suing everybody! it's time for JavaOne!
A whole lot has changed since last year, Sun Microsystems was acquired by Oracle, Kohsuke left Snoracle to found InfraDNA and Hudson has continued to power on as the single best continuous integration server on the planet.
While the tickets for Oracle OpenWorld/JavaOne are just as outrageously expensive as they were last year, we are hosting a meetup/hackathon/continuous-drinking-contest at Digg the Sunday prior. We have not yet set any kind of agenda, but some core Hudson hackers and plenty of plugin developers should be in town so it should be a great time hacking on and/or with Hudson.
RSVP Here! * When: September 19th, 1:00 p.m. * Location: Digg's Office: 1040 Mariposa St - Suite 100, San Francisco, CA 94107
Note: Unlike last year, we're trying to organize this with Meetup.com, if you experience any difficulties RSVPing let us know
Hudson User Meet-up in Copenhagen/Oslo
I'll be in Copenhagen from 9/5-9/7 and in Oslo 9/8-9/9 to present in JavaZone. I'd like to take advantage of the opportunities and have user meet-up events in those cities. Depending on the number of participants, it could be just a drink in a bar, or a talk in a meeting room.
So if you are:
- in those cities,
- available in the evening of 9/6, 9/8, or 9/9, and
- willing to attend such an event,
... then please let me know.
Also, if you have an office in those cities and willing to provide a space for an event, that would be extra appreciated!
Christian Schaefer: Options for setting up a Doctrine database connection when PHPUnit testing symfony plugins
It is rarely the case that your unit tests actually test your database. It is however not so rare that the code your unit test tries to cover needs a database connection of some sorts.
In symfony 1.x you will find quite some tightly coupled code. Together with Doctrines (1.x) implementation of the active record pattern you will get a lot of exceptions complaining about no open database connection.
So if your tests need a database connection how should you do that?
I created a little experiment to test setting up database connections. If you’re interested you can reproduce those experiments with the sources on GitHub.
I basically tried a few combinations of the following code.
Setting up a database connection using the settings in the fixture projects databases.yml Setting up a database connection using Doctrines mock adapter FindingsYou should always set up a database connection using the setUp() method of your testcase or a test method itself if it is the only method requiring a database connection. This way you only use the database when you actually need it.
I am still pretty amazed that using the mock adapter shows no functional difference to sqlite::memory: and is using up the same amount of memory.
Using –process-isolation on PHPUnit when executing a testcase or testsuite will drastically reduce the memory consumption but at the time of writing this (using PHPUnit 3.5RC1) it will produce a strange runtime exception when the database connection is made in the bootstrap file.
Oh and on the GitHub page you can also see the results of the experiments.
Typemock Sponsors See# Party 2010 (#ssp2010)
Location: Kreuzlingen, Switzerland
The premiere See# Party in Kreuzlingen, Switzerland (on the shore of Lake Constance) gets underway tomorrow, offering a full-day of education with 16 speakers/sessions, and Typemock is proud to be a sponsor.
We caught up with See# Party organizer, Juergen Gutsch, to discuss his journey from ASP developer to conference organizer, organizational challenges, and open-source side projects.
Juergen’s official bio:
Juergen Gutsch works at the ASS.TEC Inc. as a software developer, team leader and leader of .NET development. Apart from his family and job, Juergen runs his own .NET User group ".NET-Stammtisch Konstanz-Kreuzlingen" and blogs about "ASP.NET and more..." at ASP.NET Zone.
TM: First, congrats on the conference. Tell us about your journey from ASP developer to event organizer.
Juergen: Right, I started out as a classic ASP developer and heavily used the community content at aspforum.de (now ASP.NET Zone). Over time, in addition to using, I started helping other novices and soon began doing community work. Later, because I contributed so frequently, I was asked to be a moderator on aspforum.de. When aspforum.de was renamed ASP.NET Zone, I began blogging about ASP.NET.
Blogging was not enough for a community-addicted geek like me and, because there was no .NET User Group within two hours of Konstanz, I unsuccessfully tried to start .NET User Groups in Konstanz (Germany) and Kreuzlingen (Switzerland)—due to lack of interest.
A year later, with a lot of help from Swiss ASP.NET MVP Peter Bucher, we successfully founded .NET- Stammtisch Konstanz-Kreuzlingen, the first .NET User Group to span the borders of Germany and Switzerland.
While leading the NUG and visiting different conferences I had the idea to organize a small conference. At first it only was an idea, but soon other User Group members had the same idea and asked me to organize a conference for .NET developers in Germany, Switzerland and Austria—giving birth to See# Party.
TM: Were there any special challenges to organizing See# Party?
Juergen: The first and biggest challenge was the time. From conception to the day of the event—we organized everything in only four months(!!). The second challenge was to convince potential sponsors that our premiere event would be successful. We also tried very hard to include as many different speaking topics as possible—to appeal to as many .NET developers as possible. Next year will be easier. :)
TM: What do See# Party attendees have to look forward to at the event?
Juergen: Attendees will get a full day of interesting sessions about developing with .NET technologies from a number of great speakers including Stefan Lieser, Laurent Bougnion, Golo Roden, Rainer Stropek, Thomas Schissler, Roland Weigelt and many more.
In addition, there will be plenty of networking time and even lunch sessions.
TM: Any interesting side projects to promote?
Juergen: I’m supporting the open source Inversion-of-Control container, LightCore, which is developed by the ASP.NET MVP Peter Bucher. If you want to have a lightweight and very fast IoC container, then take a look at lightcore.ch
Typemock is proud to sponsor See# Party and will be raffling two Typemock Isolator licenses at the event plus a special offer for all its attendees. Be sure to attend Stefan Lieser’s session on Typemock Isolator and Brownfield Projects for an additional giveaway.
Typemock Isolator makes unit testing easy. It’s easy to learn, easy to use, and includes powerful features that make it a must-have tool for .NET developers. Isolator supports all .NET technologies including, WCF, Silverlight, ASP.NET, WPF and SharePoint.
If you would like to know more about how Typemock Isolator makes unit testing so easy, or if you have an event you would like us to sponsor please email me at britt [at] typemock [dot] com and let's chat about it.
-Britt King
Christian Schaefer: Why Doctrine_Core::getTable(BarFoo) is not such a good idea.. when PHPUnit testing a symfony plugin
If you have a look at the symfony and Doctrine documentation you will notice that whenever you want to get the table object for a model you will call Doctrine_Core::getTable(‘ModelName’).
Apparently this is considered a best practice however I came to thing quite the opposite.
As you probably know I am quite keen on the topic of unit testing and that is exactly where Doctrine_Core::getTable() gets annoying.
It’s a static method that will be called in many methods of your classes. Mostly actions and components I suppose but also in other places.
Now when you want to test those methods that include a static call like this you will notice that you need to bootstrap a lot of symfony and Doctrine. Many times you will also need to open a database connection. But the method you want to test only calls to database related methods.
I would like to be able to mock all these database related methods in order to optimise execution speed of my unit tests. However you can not mock static methods (with PHP3.5 and PHPUnit 3.5 you will be able to) which means that you need to connect the database.
This may all sound a bit loopy but I just spend several hours optimising unit tests replacing calls to Doctrine_Core::getTable(‘BarFoo’) with new BarFooTable().
CloudBees announce Hudson-as-a-Service
CloudBees announced the beta availability of their new Hudson-as-a-service "HaaS" today. I see this as yet another validation to Hudson, and as such, I welcome this new addition to the community and wish them well! — more companies betting on Hudson means we'll get more investment to the project, which is all goodness for Hudson users. It's been 5 months since I left Oracle to start InfraDNA, and I was initially worried about a possible negative impact on adoption, but instead Hudson has shown with no sign of slowing down (see picture on the right, from Andrew's report, which shows # of estimated active installations that participates to our usage stats survey). And InfraDNA is going well too - we've helped companies big and small to improve their Hudson usage/adoption, and our commercial value-add Hudson distribution is getting plenty of interest.
Hosted Hudson offers an interesting trade-off, compared to on-premise Hudson. On the plus side, given the current hourly pricing of public clouds like EC2 and Rackspace, you get a better pricing model, as CloudBees charge by minutes. You also get rid of machines and upfront cost, which is great for small business. On top of that, you can also expect them to gradually develop more value-adds and better integration to various other pieces, which can get really interesting.
On the down side, you have less control over the environment that runs the builds, and you do not have access back to your intranet environment (think databases that you need to talk to, for example.) Also, in the current pricing (8.5 cents/hour of EC2 vs 1 cent/minute of CB), if your build takes longer than 9 minutes, you'll save more by just using Hudson EC2 plugin.
On a related note, I think one of the sweet spots is Hudson that's well integrated with on-premise cloud solution. As you can see in the discussion with Liferay Hudson setup, with sufficient load it gets cheaper to have your own hardware, and many companies need some degree of control to the build/test environment that matches with their production environment. Plus with those on-premise virtualized environments, you can do snapshots and forks, which can be made to do very interesting things.
Finally, I think the part that everyone can agree on is that the elasticity of build environment is hugely useful to the CI environment, as I discussed in my JavaOne 2009 talk (slides.) I'm very happy to see that the foundation work we've made in Hudson for this is getting validated more and more, and I think the added elasticity will drive a lot more changes in Hudson and more broadly into the way we develop software. It is an exciting time!
Debugging the Undebuggable
I bumped up against an interesting problem today. I was trying to write a unit test for our CRM code (I’ll write about my endeavor in a another post). 
Anyway, I was trying to test a method (a WebMethod, actually) that was inside a class, which was inside an asmx file. Strangely enough, I never did that before, and was ready to conquer another framework with Isolator.
I was just looking to add a reference to the site from my test project. But that did not work – apparently you can’t add a reference to a site project. The next surprise (to me. Those doing it everyday, probably have figured this out eons ago) is that when you build a site, you don’t get a ready-made bin directory where I expected it would be.
It did not dissuade me. I took my trusty Reflector with me and found out that there is a bin directory under the PrecompiledWeb folder, and an assembly called App_Code.dll contains my class. I added the reference in my test project directly to this assembly. Then I went on to write a test.
Expectedly, my test failed a couple of times (I was using the Act-Assert-Arrange method for writing tests). I looked at the code, added some Isolate.Fake.StaticMethods<>, and then when it insisted to fail, I decided to debug. Immediately I figured that I couldn’t step into the class. I looked for PDB files, but couldn’t find them (probably looking in the wrong places). I tried putting a Debugger.Break command in my class, but that did not work either (probably due to some caching or something. As you’ve figured out by now, I was not really in a research mode).
So how can I debug this class, without breaking a sweat?
I took the class file (myclass.asmx.cs) and added a link to it in my test project. Presto. Now the class-under-test is in the test project. I added a couple of missing references, and the class was now debug-able. The test was completed a few minutes later.
We always talk about easy unit testing. And it is easy when you know how, including when you have this kind of ammo in your bag of tricks. When you learn a trick – teach others - they deserve to know as well!
What’s the coolest way that you found to go around a testing problem?
Christian Schaefer: Applying best practices for PHPUnit testing symfony plugins
By now I have been writing quite a bit about how to utilise PHPUnit when developing symfony plugins. But symfony is of course still bundled with lime so before starting right away every plugin needs to be prepared with small changes like adjusting the bootstrap.
And because all these little changes have to be repeated over and over again for every plugin you start they tend to get tedious.
But I’ve got an idea!
Well credit where credit is due: it was actually Stefan Koopmanschap (skoop) who initially gave me the idea of putting my findings and best practices into a plugin.
So what is to be expected?
Well so far I plan the following three features:
- A symfony task to change the default test bootstrap to work with PHPUnit
- A symfony task to create a best practice phpunit.xml.dist
- A symfony task to create skeleton test cases for classes in your project
Of course the plugin itself will be PHPUnit tested (eating my own dog food).
What would you like to see implemented? Feel free to comment on quora.
A Smattering of Selenium #24
A bit late, but I’m in California for a Selenium Developers Meetup and my body doesn’t quite know where it is temporally.
- Don’t forget that tomorrow is the next meeting of the San Francisco Selenium folks which seems to be running a crowd sourced “Let’s stump Jason with our problems” session. Most of the ‘main’ Se folk will be there.
- Test design theory is something that I have yet to really see covered much, so here are three articles on the similar idea of what to test and what to skip.
- Contradiction: Test Everything, but not Accessors? by Ron Jeffries
- don’t test for blocking conditions: an example by Chris McMahon
- Every automated test should do ONE thing really well by Adam Goucher (me)
- Another simple build radiator is just a darn cool re-skinning of Hudson which, while not as fun, is super useful in communicating build status
- Simon started to explain some of the work going on in the guts of Selenium WebDriver in Going Atomic: Why?
- For those people who loiter in the #selenium irc channel, you have likely seen ‘selbot’ in action. If you wondered where it came from you can read the details from Sauce Labs in Introducing selbot
- Atlassian is a pretty big user of Se and has a post called push my buttons which explains the myriad of ways you can send a key in Se 1.x. Which IIRC is one of the major improvements that Se 2 provides.
- The march of Flex Pilot continues and so the blog posts from users are starting to appear including Selenium Testing with Flex Pilot
- I was pleading for help on twitter last week and this cool use of the JUnit 4 @Rule annotation to get screenshots on test failures was provided
- If you are using CruiseControl.NET then Integrating Selenium Tests into CruiseControl.Net via NUnit is likely going to deliver value
- Silverlight UI testing with Selenium and Ruby is the first article I think I have seen on the subject. Of course, my memory isn’t so hot at time…
Christian Schaefer: [Best practice] How to ship PHPUnit configuration
PHPUnit offers quite a lot options to be set as arguments on the commandline. However this is tedious when typing over and over again.
For this reason you can create an XML configuration file phpunit.xml that will automatically be used by the phpunit binary.
Now you may want to include this configuration file in your projects sourcecode to be used by all participating developers and your continuous integration server. But how?
Well, you could just commit the phpunit.xml to you repository right?Well, yes. But then all developers who want to checkout and work on your project will have to use these settings or going through the trouble of maintaining local changes to the configuration or specifying a different one using the commandline.
No! Use phpunit.xml.dist instead.Sebastian made me aware of this and he is right. If you provide a phpunit.xml.dist(ribution) instead then every developer can chose whether to use your configuration or his/her own.
It is also wise to ignore the real phpunit.xml for your repository using .gitignore or svn:ignore or similar. This way everybody can use the settings he/she wants without forcing them onto others.
How can my continuous integration server use the config?Simple! the phpunit binary is clever enough to use any phpunit.xml.dist file if no phpunit.xml is available.
Christian Schaefer: Setting up Continuous Integration for a symfony plugin using Hudson and Sebastian Bergmanns (PHPUnit) Template for Hudson Jobs for PHP Projects
I must admit that I have been lazy with my efforts on continuous integration lately. Eventually my server crashed unnoticed and I didn’t get any emails about broken builds anymore and by now I think I’ve stacked up some work to do.
First of course I’ve got to get my CI server up and running again, that’s why I installed Hudson again.
But there is room for improvement too. Sebastian Bergmann of PHPUnit fame spent some time on a template Hudson job for PHP projects that includes much more than PHPUnit. So I decided to use that!
GoalWhat I want to achieve is to setup a project for my symfony plugin sfImageTransformExtraPlugin using the Sebastians template.
PrerequesitesI am assuming that you already have a working Hudson installation and the following plugins installed:
- Checkstyle (for processing PHP_CodeSniffer logfiles in Checkstyle format)
- DRY (for processing phpcpd logfiles in PMD-CPD format)
- HTML Publisher (for publishing the PHPUnit code coverage report, for instance)
- JDepend (for processing PHP_Depend logfiles in JDepend format)
- PMD (for processing phpmd logfiles in PMD format)
- Template Project (for using php-hudson-template as a template for Hudson jobs)
- Violations (for processing various logfiles)
- xUnit (for processing PHPUnit logfiles in JUnit format)
Just as described in the README on GitHub we just checkout the project in to our Hudson jobs folder.
$ cd /home/of/hudson/jobs $ git clone git://github.com/sebastianbergmann/php-hudson-template.git
And then we have to restart Hudson to take notice of this new job.
The job itself is disabled as it has no subject.
Setting up the real jobSo what I want to do is to checkout the current development version of my symfony plugin from GitHub. I also have to checkout it dependencies which are symfony itself and sfImageTransformPlugin which both are available only via Subversion.
I start by adding a new “free-style software project” job with the name “sfImageTransformExtraPlugin”.
First I configure the GitHub source and under the advanced options I configure it to be checked out into a local subdirectory “sfImageTransformExtraPlugin”.
Next I add a build step “Invoke Ant” and under advanced options I point it to the build.xml at “sfImageTransformExtraPlugin/build.xml”.
Last thing to configure is to “Use publishers from another project” and I enter “php-hudson-template” as the template project.
And that all you have to do to setup the project in Hudson.
But of course that’s not all. Two produce all the reports that the template should process and to checkout and update the dependencies we need two more configuration files which are both part of the plugin.
This is more or less a copy of the example from Sebastians GitHub Page with soem slight modifications.
The first target “update” will check out the dependencies from symfonys Subversion repositories in parallel to the plugin itself. The plugin is configured to assume symfony and sfImageTransformPlugin at these locations.
All artifacts such as coverage reports and metrics will be written to a directory “build” which also lies in parallel to the plugin source. All together will produce a directory structure like this.
/path/to/hudson/jobs/sfImageTransformExtraPlugin/build/ /path/to/hudson/jobs/sfImageTransformExtraPlugin/sfImageTransformExtraPlugin/ /path/to/hudson/jobs/sfImageTransformExtraPlugin/sfImageTransformPlugin/ /path/to/hudson/jobs/sfImageTransformExtraPlugin/symfony/
But not all reports that are expected by the template are being produced by this build.xml. The PHPUnit specific reports are configured in the phpunit.xml file.
Adjust these two configuration files for your plugin to your needs and you’re ready to go.
In the following weeks I will write some posts explaining all the results you can now see in your Hudson installation (or in mine).
ConclusionThis template makes setting up Hudson for PHP development so much easier! Great thanks to Sebastian for his awesome work!
Hudson / Sauce OnDemand webinar
On September 1st, I'll be presenting in a Sauce Labs webinar about Hudson and Sauce OnDemand. The talk will discuss how Hudson can be used with Sauce OnDemand, naturally, but it'll also cover broader Hudson/Selenium integrations.
Please register to this free event, and looking forward to seeing to you virtually.
Thanking our Community!
Since January 1′st Mikeal, MDE and I have been really busy with new adventures but I wanted to thank our community for stepping up and continuing to improve Windmill.
The web sites, getwindmill.com and the github project have been continuing to get more and more traffic all the time. With spikes of over 1000 users on getwindmill.com and 381 users in a day on the github project a couple months ago (averaging around 200 users a day I can safely say that Windmill is continuing to grow it’s user base.
We haven’t done a release since Windmill 1.3, and there have been lots of changes to infrastructure, patches and issues fixed so I think in the coming weeks my plan is to package up and release Windmill 1.5.
There is no game plan carved in stone, but I would like to spend some time sprucing up the IDE theme as it’s starting to look a bit dated.
I will be at both CouchCamp and JS EU in Berlin next month, if any Windmill’ers are attending it would be great to meet up for a beverage.
Thanks for your patience and persistence everyone!
Cheers,
Adam
Isolator++ Beta News
The latest beta of Isolator++ is up on the site. Here are a couple of the features that you now can do:
- Support for VS2010. Apart from the support for the IDE, the examples also contain a solution for VS2010, so you can look at what’s new there.
- Faking global functions. If you look at the example on the Isolator++ product page, you’ll see how fopen is no longer a problem for testing.
- Faking private methods. Nuff said.
- Future objects : those pesky things you create with "new" in the code-under-test, can now be faked.
- Live objects: Let's not forget objects you create in your test, but are not fake, and you just want to change their method's behavior.
And of course there are fixes of bugs and more features creeping in, as much as we can. Check out the beta and let us know what you think about it.
Hudson Anonymous Usage Data
In late 2008, the Hudson team released version 1.264 which added an anonymous reporting feature (you can opt-out in the "Manage Hudson" screen). The reporting feature has been sending information back to the Hudson team to help us understand how Hudson is used in aggregate; the info being reported includes the number of jobs configured, slave configurations, what plugins (and what versions of those plugins) are installed, and more. This data has not been available publicly until now! The raw data needed to be decrypted and scrubbed of any potentially identifying information, such as non-public plugin names or usernames in snapshot versions. We've finally scrubbed the data and are making it available!
The data is currently in monthly JSON bundles, organized by unique install key. We've filtered out reports of installations without any jobs configured, as well as any installations with only one report in a given month.
If you'd like access to the data, please send an email to dev@hudson.dev.java.net or jump onto the IRC channel and ask - we'll send you the URL and a private username/password which you'll need to access the info. We're also planning to do more analysis of the data ourselves, for now feast your eyes on this spreadsheet, which shows the total number of unique installations seen per month and the number of unique installations of each publicly available plugin per month.
(Andrew is a core committer to Hudson and the author of numerous plugins. He's the build guy at Digg, who, by the way, are hiring!)Hudson 1.372 sets sail
Last Friday the Hudson team rolled out a small 1.372 with two enhancements following the critical 1.371 release on Monday. Not a whole lot to say about this release other than go get it!
Enhancements- Persist matrix-based security settings in a consistent order (issue 7138)
- Jobs can now use boolean expression over labels to control where they run.
You can go grab the latest .war file straight from our OSL mirror or if you're using a native package, use your package manager to upgrade.
Going Atomic: Why?
This is the first in a series of technical posts by me about the internals of Selenium WebDriver. If you’re not interested in technical nitty-gritty, then feel free to step away now.
Still here? Excellent.
Let’s take a step back to just before the Selenium and WebDriver projects merged. There were, very obviously, two separate codebases. Looking closer and with a slightly different perspective, there were more than this. We used the test suites for webdriver to define the behaviour for multiple, largely independent, driver codebases. The IE driver was written in C, the HtmlUnit driver in Java and the Firefox driver is largely Javascript, and so on.
This means that there was a lot of “congruent code”: code that performed the same function but was implemented in a different way. The natural result of this was there was the possibility for behaviour to diverge between drivers. Worse, it meant that when a bug was found, we had to check it in every browser, and it wasn’t certain that an individual could actually fix the code. After all, not everyone is comfortable writing in all the languages we use on the project, or is au fait with all the technologies. For an Open Source project like Selenium, this is a major problem: we rely on a relatively small core of key developers backed up with a far larger team of individuals submitting small changes and fixes. Anything that makes it harder for us to function effectively as a development community is a Bad Thing.
So, we wanted a way off the island; a mechanism that would make it easy to share code between the various drivers and selenium core, that allowed us to fix a bug in one place only and have that fix ripple out to every driver that made use of this mechanism. More importantly, it had to be easy to use, and for someone not familiar with a raft of languages and technologies to quickly get started with.
What would this mechanism look like? Well, there’s a few things that feed into this, but the most important one, was that a majority of the code we’d think of merging was querying the state of the browser (“find an element”, “get the value of this attribute”) and, as Jason Huggins would point out to me at the drop of a hat, the natural language for querying the state of a browser is Javascript. One of the nice things with Javascript is that it’s possible to get a nice, fast development cycle going in it. Just modify a test, save and then hit “refresh” in the browser. That’s kind of attractive. Better still, there are a lot of developers familiar with Javascript.
So, we decided to use Javascript.
Because this shared code was to be composed of the smallest useful fragments of functionality required for browser automation we decided to refer to them as “Browser Automation Atoms”, or “atoms” for short. Rather than write them from scratch, the easiest thing to do was to extract them from the existing code — this is stuff that’s been battle-tested, so we know it’s robust.
There was one very obvious fly in the ointment: not every driver is written in Javascript. Although we have a mechanism available in every browser for executing JS, it’s wildly inefficient to dump an enormous lump of code on to the JS engine of the browser whenever you want to query the DOM. After all, most of the code would not be needed, and not all JS engines have been created equal. Some are blazingly fast. Others, not so much.
It would also be nice to break the code up into manageably-sized modules, rather than being in a single, monolithic file, which implies some clever “module loading” capability. Except this code isn’t always going to be executing inside an environment where writing “script” tags to load additional scripts is possible. You can’t do that in the guts of a firefox extension, though you can load files other ways. However we tie modules together will need to cope with that.
Ah! These opposing requirements: small modules containing the functions we want to use, no extraneous code, and for everything to be in a single file in order to minimize the pain of loading additional modules. That doesn’t sound like a very compatible list. How we resolved those differences is the topic of my next post….
Sebastian Bergmann: PHPUnit 3.5: Less $this Required
The feature discussed below has been removed from PHPUnit due to community feedback.
Over the years, I have gotten quite a few "complaints" from PHPUnit users that they do not like typing $this-> as often as they have to:
<?php
class StackTest extends PHPUnit_Framework_TestCase
{
public function testPushAndPop()
{
$stack = array();
$this->assertEquals(0, count($stack));
array_push($stack, 'foo');
$this->assertEquals('foo', $stack[count($stack)-1]);
$this->assertEquals(1, count($stack));
$this->assertEquals('foo', array_pop($stack));
$this->assertEquals(0, count($stack));
}
}
?>
As of PHPUnit 3.5, they can write test code that requires less $this-> statements:
<?php
require_once 'PHPUnit/Framework/Assert/Functions.php';
class StackTest extends PHPUnit_Framework_TestCase
{
public function testPushAndPop()
{
$stack = array();
assertEquals(0, count($stack));
array_push($stack, 'foo');
assertEquals('foo', $stack[count($stack)-1]);
assertEquals(1, count($stack));
assertEquals('foo', array_pop($stack));
assertEquals(0, count($stack));
}
}
?>
Here's hoping that this makes some people happy :-)
HudsonMobi 2.0 hits the Android Market
The folks over at LMT Software just released their HudsonMobi 2.0 to the Android market. This release of HudsonMobi brings a lot of the features to Android that iPhone/iPad users of HudsonMobi have enjoyed for some time.

Features unleashed to Android users in this revision of the app are:
- Full Android user-experience with Menu and back controls
- Embedded artifact viewer! For archived build artifacts that are text-based, you can view them directly on your handset.
- Access to the build history and changes for a job.
- Quick and easy access to a job's last build\
- Restyled and updated user-experience, making HudsonMobi "feel better" on an Android device

If you want to get HudsonMobi for free from the Android Market, whip our your phone and take a picture of its QR code:
