TeamCity + Codeception + Laravel = Automated build testing

Joe • July 29, 2014

laravel php testing

I'm going to start out by saying this: I'm probably not doing this the "right" way. I've not been able to find anything that really pushes me into the "right" way so I'm documenting what I currently have working in hopes that someone will come along and show me a better way.

The project I'm working with is for my day job and covered by some signed documents so I can't really divulge anything specific. What I can talk about is it is a Laravel 4.2 application using Angular, and redis for some real time functionality. My goal for this application is to write maintainable code, write tests, and take advantage of some sort of continuous integration / deployment setup so we can go home on time.

Since it's not an open source app the free version of Travis-CI is out of the question. And since this is the only project we're looking at doing continuous integration / deployment with, we're just not ready for private Travis-CI either. I looked into PHPCI and while it looks like a really great project, I didn't think it had everything I needed (I could be 100% wrong on this). I also set up Jenkins and followed a guide specific to PHP. This failed miserably and was likely due to my own inexperience.

Enter Team City. I am a JetBrains fanboy. I LOVE Phpstorm. So finding a CI solution that was made by JetBrains AND free? I was sold. I followed all the documentation and grabbed the PHP Meta Runners and set up my project and everything seemed to be glorious. I set up VCS triggers so that when we pushed changes to the master or dev branch it would fire off a build. The build test would pull down source, run composer, run bower, and then run phpunit.

This worked great until I saw Jeffery Way's Laracasts video on Codeception. I spent some time getting Codeception added to our app and wrote some acceptance tests that used the basic PHP browser.

Now that I had acceptance testing I needed a way to get TeamCity to run my acceptance tests. If you are not familiar with acceptance tests Codeception runs them against a very basic PHP web browser by default. You can configure selenium but it was beyond my current scope.

If the hack works, is it still a hack? Probably so...

Since you can have any number of build steps in a build configuration I set up build steps to run php artisan serve before running Codeception. Since I didn't want to leave the server running, I used screen to throw the command into a detached screen, then after Codeception ran, I killed off that screen. To run the command: screen -S server -d -m php artisan serve To kill off the session later: screen -X -S server quit This worked surprisingly well as long as Codeception didn't fail any tests. I could have set the kill command to run "Always, even if build stop command was issued" however this felt like a bad way of handling this.

Better way? Maybe...

I created a vhost on the build server to handle my project exactly like it is configured in vagrant. I disabled my hacky screen related build steps and added another build step before codeception that copied the source from the working build directory to where the vhost was pointed at /var/www/project.dev. Now my acceptance tests run against an actual server mimicking production.

My build tests are running, unit tests get run, acceptance tests get run and I feel good about the code getting deployed. However it still feels hackish. I wasn't able to find anything meaningful so I thought I'd write all this up, throw it out there for the internet to tell me how wrong I may be. If you have a better way of doing what I'm trying to accomplish, I'm interested to hear about it.