What is a Walking Skeleton?
A “walking skeleton” is an implementation of the thinnest possible slice of real functionality that we can automatically build, deploy, and test end-to-end [Cockburn04]. It should include just enough of the automation, the major components, and communication mechanisms to allow us to start working on the first feature. We keep the [...]
What is a Walking Skeleton?
A “walking skeleton” is an implementation of the thinnest possible slice of real functionality that we can automatically build, deploy, and test end-to-end [Cockburn04]. It should include just enough of the automation, the major components, and communication mechanisms to allow us to start working on the first feature. We keep the skeleton’s application functionality so simple that it’s obvious and uninteresting, leaving us free to concentrate on the infrastructure. For example, for a database-backed web application, a skeleton would show a flat web page with fields from the database.
via Nat Pryce and Steve Freeman – Growing Object-Oriented Software, Guided by Tests on page 32
This means that in order to start writing acceptance tests we need an environment that we can run them against. Of course we can consider them failing test if the skeleton doesn’t exist and the expected features don’t work but that’s not our point. We need to agree on several issues to start working. What language will we be using? What platforms do we want to work on? How will we utilize a continuous integration server? What SCM will we use? What metrics will guide us?
Language: PHP5.3
Platforms: Linux, OsX, Windows
CI server: Hudson @ http://hudson.alternateillusion.com/job/Munchkin/
Build manager: ANT
Package manager: PEAR
SCM: Gitgit clone git://git.assembla.com/munchkin.gitmore info
Metrics: CodeStyle, Code coverage, PMD, Duplicate Code, Open tasks
Domain: http://alternateillusion.com/munchkin - for now
Ticketing: assembla
Iteration length: 4 weeks
We still don’t have a clue about what kind of data-backend we’ll be using. Right now we only know that we should be considering some NoSQL solutions besides MySQL. For our current phase the database is irrelevant and abstract. One golden rule in agile development is do the simplest possible thing to achieve your goal. We won’t go into writing a bunch of requirement specification and the usual waterfailistic documents.
From this point we’ll start to manifest our project. We’re going to utilize Git and Ant to kick-off our evolving code. We’ll create an empty repository and a simple build.xml to drive our current (and further) development cycles (test, deploy, package). You’ll learn how to have basic tests without any extra software, how to use Git submodules and how to jail the functionality of pear into a custom project directory.
So we have come to a point where the spark ignites.
To kick-off the skeleton we first need a working web-server with PHP5.3 and PEAR and an Ant ( >= 1.7) installation. We believe you can handle these by yourself.
The code we’ll be writing from now on will be available in our Git repository. If you’d like to create the code parallel to us, then do the following steps:
git init Munchkin (this will create a local repository for yourself)git commit --allow-empty -m'Master init'git remote add ai git://git.assembla.com/munchkin.gitgit fetch aigit checkout -b ai remotes/ai/masterYou’ll get an ai branch that will hold the current state of the assemble repository with the actual codebase.
Whenever you’d like to see the state of the assembla branch, you have to do the following steps:
- Change to the ai branch
git checkout ai- Pull the current version
git pull ai master:ai
This tells Git to pull in the state of the master branch of the ai remote to your local ai branch.- Don’t forget to change back to the master when done
git checkout master
So first thing’s first, we need an environment. We’ve found that a project-based deployable environment is much more manageable than documentations about “build yourself a system that can run our software” so we’ll add all further dependencies in our build/deploy mechanism. This means that for the project to emerge, we’ll only need a build.xml that Ant could use. Let’s create the first file in the repository. Let’s switch to the master branch (which will hold your local version of the project)
git checkout master should do the trick. You could verify the switch with git branch which should show a
Your current branch is the one where the asterisk is.
Open your favorite php editor and create a new file in the project root, named build.xml. Add a few rows as shown below.
1 2 3 4 5 6 7 8 9 | <?xml version="1.0" encoding="UTF-8"?> <project name="Munchkin" default="build"> <description> http://www.alternateillusion.com/munchkin-articles </description> <target name="build" description="Build the project"/> </project> |
Save the file and try issuing an ant command in your project root. You should see something like this:
If all is right:
git add build.xml – add the files to the repo
git commit -s -m'Empty version of build.xml' – commit your work
What is the -s flag?
-s represents “sign-off”. The meaning is found after a bit of searching:
Sign-off is a requirement for getting patches into the Linux kernel and a few other projects, but most projects don’t actually use it.
It was introduced in the wake of the SCO lawsuit, (and other accusations of copyright infringement from SCO, most of which they never actually took to court), as a Developers Certificate of Origin. It is used to say that you certify that you have created the patch in question, or that you certify that to the best of your knowledge, it was created under an appropriate open-source license, or that it has been provided to you by someone else under those terms. This can help establish a chain of people who take responsibility for the copyright status of the code in question, to help ensure that copyrighted code not released under an appropriate free software (open source) license is not included in the kernel.
via Stack Overflow
Munchkin will use sign-offs!
As mentioned above we’ll use pear as package manager. There is a usage mode of pear that is not as commonly known as it should be. You can create custom configuration files to drive pear commands with which enables you to handle project based dependencies. You wouldn’t need to litter your global space with packages that only one project needs. From our point of view we’ll utilize this feature via our build script. In order to achieve that we’ll need a 3rd party tool that enhances ant’s task-base with some neat macros.
To set up these files you need to add them as a Git submodule:
git submodule add git://github.com/meza/ant-helpers.git ant-helpers
This will create an ant-helpers directory in your root and a .gitmodules file which holds the Git specific information about this module. You need to commit these files too:
git commit -s -m'Added ant-helpers to the project'
More on Git submodules on progit.org
Your project root should look like:
We need to include the ant-helper files in order to use the pear related features. Modify your build.xml to look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?xml version="1.0" encoding="UTF-8"?> <project name="Munchkin" default="build"> <description> http://www.alternateillusion.com/munchkin-articles </description> <!-- import ant-helpers --> <import file="${basedir}/ant-helpers/shell.xml" /> <import file="${basedir}/ant-helpers/pear.xml" /> <target name="build" description="Build the project"/> </project> |
This will enable us to use the <pear-generate-config>, pear-install and the <pear> tasks. We need to define a directory where we’ll hold the vendor files and we must exactly know what the pear config file will be. We define some top-level properties that all targets will be able to reach.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?xml version="1.0" encoding="UTF-8"?> <project name="Munchkin" default="build"> <description> http://www.alternateillusion.com/munchkin-articles </description> <!-- set default properties --> <property name="vendor.dir" location="${basedir}/vendor"/> <property name="pear.config" location="${basedir}/.pearrc"/> <!-- import ant-helpers --> <import file="${basedir}/ant-helpers/shell.xml" /> <import file="${basedir}/ant-helpers/pear.xml" /> <target name="build" description="Build the project"/> </project> |
With all utilities present we can write all initially known targets.
“build” is the main target in the file. It has a depends attribute which tells Ant that the comma separated other existing targets must be called before this one could be executed. We’ve cerated a “check-pear” task which checks for the ${pear.config} file to be present. If it can’t be found the build fails informing us that the task init must be issued before any further steps. “init” depends on two other tasks. It first removes all left-over files (if any) with “distclean” task, and generates the pear config file with “pear-generate-config“.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | <?xml version="1.0" encoding="UTF-8"?> <project name="Munchkin" default="build"> <description> http://www.alternateillusion.com/munchkin-articles </description> <!-- set default properties --> <property name="vendor.dir" location="${basedir}/vendor"/> <property name="pear.config" location="${basedir}/.pearrc"/> <!-- import ant-helpers --> <import file="${basedir}/ant-helpers/shell.xml" /> <import file="${basedir}/ant-helpers/pear.xml" /> <!-- Remove all generated content --> <target name="distclean" description="Remove all generated content"> <delete dir="${vendor.dir}"/> <delete file="${pear.config}"/> </target> <!-- Clean and prepare the first build --> <target name="init" depends="distclean, generate-pear-config"/> <!-- Generate the pear config file --> <target name="generate-pear-config" depends="distclean"> <pear-generate-config peardir="${vendor.dir}"/> </target> <!-- Check if the pear config file is present and fail if not --> <target name="check-pear"> <fail message="Run ant init"> <condition> <not> <available file="${pear.config}"/> </not> </condition> </fail> </target> <!-- Build the project --> <target name="build" description="Build the project" depends="check-pear"/> </project> |
In order to build your project you’ll have to execute the following commands in your project root:
ant init
ant
You’ll notice here that there are some extra generated files that we you wouldn’t like to see in the repository. This could be avoided by not adding it via git add, but there’s a much more sophisticated way. Create a file called .gitignore and add the following contents:
This will tell Git to simply ignore these entries for good. To make this final you have to add it to your repo:
We’re done with our buildfile for now, so we can add that too:
git add build.xml – add the files to the repo
git commit -s -m'Utilizing ant-helpers and ignore file' – commit your work
So we’ve managed to create a nice little build file, but this is still not a ‘walking skeleton’. What do we need for that? A test! A test that proves us right. A test that can ensure us that our skeleton really walks. But what could be tested inn such early state? Does the domain exist? Is it giving us what we expect? But what do we expect from it? The solution is much more easier than you’d think. We expect it to give us a 200 OK response (means the url is existing). But how do we test it? We could use Selenium / PHPUnit or some custom php script to verify the url exists. Luckily we have already created an Ant buildfile which is just suitable for our needs and as this step is vital for our project, the test should fail the build if the url is not present.
We’ll add a new property describing the url:
And we add a new target that will fail if the url is not found:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | <?xml version="1.0" encoding="UTF-8"?> <project name="Munchkin" default="build"> <description> http://www.alternateillusion.com/munchkin-articles </description> <!-- set default properties --> <property name="vendor.dir" location="${basedir}/vendor"/> <property name="pear.config" location="${basedir}/.pearrc"/> <property name="project.url" value="http://alternateillusion.com/munchkin_unexisting"/> <!-- import ant-helpers --> <import file="${basedir}/ant-helpers/shell.xml" /> <import file="${basedir}/ant-helpers/pear.xml" /> <!-- Remove all generated content --> <target name="distclean" description="Remove all generated content"> <delete dir="${vendor.dir}"/> <delete file="${pear.config}"/> </target> <!-- Clean and prepare the first build --> <target name="init" depends="distclean, generate-pear-config"/> <!-- Generate the pear config file --> <target name="generate-pear-config" depends="distclean"> <pear-generate-config peardir="${vendor.dir}"/> </target> <!-- Check if the pear config file is present and fail if not --> <target name="check-pear"> <fail message="Run ant init"> <condition> <not> <available file="${pear.config}"/> </not> </condition> </fail> </target> <!-- Check if the project's url returns a 200 --> <target name="test-project-url"> <fail message="Project url does not exist"> <condition> <not> <http url="${project.url}"/> </not> </condition> </fail> </target> <!-- Build the project --> <target name="build" description="Build the project" depends="check-pear, test-project-url"/> </project> |
If you run ant now you’ll get
We just wrote a failing test!
That is the first goal of TDD. And when you have a failing test, make it pass. In our case we’ll write the correct url to the property.
If all is right:
git add build.xml – add the files to the repo
git commit -s -m'First acceptance test' – commit your work
We’re almost done! Because we wouldn’t like to have any rough dependencies we’ll allow every user to define their own values of the properties in our buildfile without modifying anything in the repository. Ant has a sophisticated feature that handles this problem. You can define a file that will hold key=value pairs defining properties. If you read this file after the default props are set, they will be overwritten by the ones in the file. So our final build.xml looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <?xml version="1.0" encoding="UTF-8"?> <project name="Munchkin" default="build"> <description> http://www.alternateillusion.com/munchkin-articles </description> <!-- set default properties --> <property name="vendor.dir" location="${basedir}/vendor"/> <property name="pear.config" location="${basedir}/.pearrc"/> <property name="project.url" value="http://alternateillusion.com/munchkin"/> <property file="${basedir}/build.properties"/> <!-- import ant-helpers --> <import file="${basedir}/ant-helpers/shell.xml" /> <import file="${basedir}/ant-helpers/pear.xml" /> <!-- Remove all generated content --> <target name="distclean" description="Remove all generated content"> <delete dir="${vendor.dir}"/> <delete file="${pear.config}"/> </target> <!-- Clean and prepare the first build --> <target name="init" depends="distclean, generate-pear-config"/> <!-- Generate the pear config file --> <target name="generate-pear-config" depends="distclean"> <pear-generate-config peardir="${vendor.dir}"/> </target> <!-- Check if the pear config file is present and fail if not --> <target name="check-pear"> <fail message="Run ant init"> <condition> <not> <available file="${pear.config}"/> </not> </condition> </fail> </target> <!-- Check if the project's url returns a 200 --> <target name="test-project-url"> <fail message="Project url does not exist"> <condition> <not> <http url="${project.url}"/> </not> </condition> </fail> </target> <!-- Build the project --> <target name="build" description="Build the project" depends="check-pear, test-project-url"/> </project> |
If you add project.url=http://my.url.com to the build.properties file (which you may need to create if you’d like to use it), the next run will test that url.
To make sure the build.properties file doesn’t get into the repository, add it to the .gitignore file so that it would look like:
Commit the changes:
git add .gitignore – add the ignore file
git add build.xml – add the files to the repo
git commit -s -m'First acceptance test with per-user config' – commit your work
We’ve created a project skeleton that is suitable for Munchkin, but still abstract enough to use it almost anywhere. You only need to modify the project name Ant url to apply this to any web project of your own. There’s no big magic and we didn’t quite use pear yet also. That will be the part of the next article. So what do we have? We have a deliverable software. It does nothing, and that’s the precise feature we expect it to do just now. There is a domain active for it. We’re sure it works. We can build the project and we have an end-to-end acceptance test.
In the next episode we’ll add pear dependencies through Ant and create our first PHPUnit driven end-to-end tests. With these present we’ll be able to hook the project to a Hudson job that will verify each and every repository updates. We’ll be introducing phpcpd, phpcs, phpmd, phploc and learn what the trends of these reports show us.
Though the title mentions initial stories, we’re holding them for the next post where we’ll start the first sprint!
Until then, you can get familiar with the global (we’ll use the pear project jail in Munchkin) setup of these tools at my post about code quality here!
Happy coding!
Other Munchkin articles
Just found this great cheatsheet on twitter by @nickfloyd.
Use it wise and be the proud creator of lots of nice clean code!
download pdf
Hi guys!
Here is a framework project. It consists of selenium 2.0 and object repository and user repository.
Use it wisely and give us credit.
https://sourceforge.net/projects/webauthfw/
We’re not superheroes
I was reading bits of Coders at work, a book of interviews to famous programmers. I didn’t like it very much: here’s why.
The first thing I noticed is that many questions are biographical. I do not care about knowing if Ken Thompson, which built Unix, worked on a PDP-10 or a PDP-11 or [...]
Product Details
Paperback: 688 pages
Publisher: O’Reilly Media; 1 edition (October 25, 2004)
Language: English
ISBN-10: 0596007124
ISBN-13: 978-0596007126
Product Dimensions: 9.2 x 8 x 1.4 inches
Shipping Weight: 2.8 pounds
Not as bad as it may look by the cover! Elisabeth Freeman relies on the feminine way of association. There are a lot of pictures, arrows, speech bubbles, acts and [...]
We sat down today with @fqqdk to have a user modeling workshop. In this session we aimed to produce a set of stereotypes that the users of our product will have. We had a hard time because the use-cases are not so distinguished from each other. Most of the people who aggregate feeds are constant [...]
Product Details
Paperback: 304 pages
Publisher: Addison-Wesley Professional (March 11, 2004)
Language: English
ISBN-10: 0321205685
ISBN-13: 978-0321205681
Product Dimensions: 9.1 x 7 x 0.7 inches
Shipping Weight: 1.2 pounds
I was holding this book in my hands a few times before I actually started reading it. I didn’t believe that a book can actually get me into a mood that extreme [...]
In gaming, a Munchkin is a player who plays what is intended to be a non-competitive game (usually a role-playing game) in an aggressively competitive manner. A munchkin seeks within the context of the game to amass the greatest power, score the most “kills,” and grab the most loot, no matter [...]
We’re proud to announce, that our PimpMyCode project has finally been launched. It’s purpose is to help all fellow PHP coders out there spending tons of time surfing for examples of testing their code. We know that how easy it is to find help in the Java world, and it’s the exact opposite with PHP.
With [...]
Product Details
Paperback: 528 pages
Publisher: Apress; 1st ed. 2005. Corr. 2nd printing edition (August 29, 2005)
Language: English
ISBN-10: 1590595084
ISBN-13: 978-1590595084
Product Dimensions: 9.2 x 7.4 x 1.2 inches
Shipping Weight: 2 pounds
I was expecting to have much heureka moments reading this book, but I was let down. Being good in encryption doesn’t mean you’re good at [...]
Product Details
Paperback: 448 pages
Publisher: O’Reilly Media; 1 edition (May 8, 2007)
Language: English
ISBN-10: 0596529260
ISBN-13: 978-0596529260
Product Dimensions: 9.1 x 7 x 1 inches
I didn’t really like the way were too over-descriptive. The knowledge inside the book is definitely makes it worth to read it. It made me actually get thinking the way of RESTful services. [...]
If you like it, please help me to have time to write :)