Showing posts with label automation. Show all posts
Showing posts with label automation. Show all posts

Sunday, May 11, 2008

Automated deployment - Why it is a good idea

Grant raised the concept of the automatic deployment in a comment on a post I made the other day about controlling test environments. I've been giving it a bit of thought of late and I've come up with a quick test you can do to see if you should automate your deployment process. As you go through the test you will also see various ways how automated deployment can improve your development practices.

Once Upon a Time...
Let me start with a tale of woe.


The past two weeks I've been working with a developer who has been lumped with some less than satisfactory code. Also lacking is a suitable development environment for him to work within. In an effort to get something suitable into test I have been working with him to solve the various problems. This past week has seen about15-25 deployments into test (don't get me started on unit testing). When he is not around another person from his team will do the work. Everyone of them at some point failed to deploy correctly.

Why? Firstly their application is made of a number of disparate components that all are deployed individually. They don't have version numbers to identify the latest build. They are deploying to a cluster. They are rushing to get late code into test. The testers don't have control of the test environment (yet).


Consider this
If your deployment is as simple as a point and click install and that is it, your failure points are: installing the right version and actually doing it (don't laugh). Two failure points, ignore the triviality for now. If you have a configuration file to manually adjust, there is another point. Add them up, one for each step you have to do in order. If you have deployment instructions. Add one more as those have to be followed, if you don't have deployment documentation add 1 million points. If you have to rebuild a fresh machine each time. Add 1 for each step. If you are smart and have a prepared image. Add a single point if you need to deploy it each time. Zero points if you don't.

I think you are starting to get what gives you points and what reduces your score. Stay with me as we go back to our example:

I don't know the full details of the application but I know there are about five components each of which needs to be deployed. So 5 * 3 (version, doing it, following instructions). Three of the installed components need to be turned on each time. So that is 3 more points. 18 is our score so far.

How many machines do you have to deploy to? One host? Score one for the number of targets Clustered array of four machines. Score 4. Pretty simple scoring system. Write this down as your targets score.

For our example we have a two hosts load balanced. So we score 2.

How frequently are you going to deploy your code? Once per iteration, how many iterations in the project? 10? Score one point each time you deploy per iteration, times iterations. Record this as frequency.

How many test environments are there? Dev, Dev-Int, Test, Non-functional, Release Candidate Integration, Pre-Production, Production? Here are seven from a in my opinion pretty regular configuration. 7 Points. Once again, in my example, just one, test. Add it up for your environment score.


Failure Points
Ok, so our formula for calculating the failure points of a deployment:

Failure Points = deployment-steps X frequency X environment X targets

Example = 18 x 2 x 15 = 540 points of failure

Not bad. You may argue that once you have tested your deployment that you shouldn't have any failures after that. It is tested after all. That is a good point, but remember we are not even talking about deployment testing here. Just vanilla dropping an application onto a box.

We (this is a team project after all, shared wins/shared losses) had 540 chances in a one week period to stuff up an aspect of the deployment process. Aside from the code failures, we had probably 10 deployment failures including not installing the code onto both machines in the cluster. Those particular defects are about as much fun to detect as a race condition.

Automated Deployment
How much you automate will directly impact the chances for deployment failure. Our two constants for the act of deployment were: actually doing it and installing the correct version.

Performing the work is now done by the auto-deployer. You still need to click the go button for certain environments. Automatic deployment implies that latest valid build is used so that problem is solved.

Individual deployment steps should be wrapped up into your installer. I mean every step. Installing software, opening ports on routers, configuration files. If you do some research you will find somebody has automated already it for you, or there is an API for it. If by chance that isn't done, do it yourself and then share the love.

Next up is the deployment to each machine on the cluster. Once again this should be handled in by your autodeployer. So that one is fixed, score a zero.

After that was the total number of deployments. That shouldn't change. As long as your autodeployer is operational and you click the go button as required. You should be down to a score of 5 (once for each environment from test afterwards).

With our example we should go from 540 failure points to 5. One for each deployment that has occured over the past week. Triggered by the test team as required. There are no other manual steps.

Bonus Feature
If the latest build is unusable for testing. Allow the testers to flag it as so (Build Quality) and have the autodeployer ignore that build for future deployments.


Conclusion
You may realise by now, that I have been a little bit over the top with my example. Furthermore, every iteration you don't deploy to every environment. You and I know this, but it won't change your score that much. You may also think of more places in which the scoring system should change. Post them as a comment and I'll put together a little spreadsheet you can use.

I am not going to tell you how to automate your deployment process. I've got an idea on one way to do it and I'll post about when I've done it. In the meantime here are a couple of other ideas to get you started (thanks to Grant for these):

  • Use PsExec
  • Use putty if you are not on a windows box
  • Via TFS Build here and here

Before I go some more juicy content: your autodeployer should not be used until you have tested it through all environments. Including deployment into production.

Tuesday, April 8, 2008

QuickTest and CruiseControl for Continuous Integration

Originally I was working on the QuickTest CI setup with CruiseControl.NET (will work just as well for .java). This never got this completed for obvious reasons, but I thought I would share my notes with you.

Here is my original post detailing the qt2NUnit xsl and QuickTest structure


You need to launch QT remotely and I suspect this is more involved than what Grant did with TeamBuild. Look at what he did, and here is a reference to someone who executed QT remotely. I recommend using Grant's C# code to correct the repository references at run-time.

After that you just need a NAnt task to transform the results.xml doc. Here is a quicktest.build Nant task.
Then merge the results with your other result files. This works well if you have unit tests being produced in the same format. All the tests cases live together in harmony. This is a good thing.

Here is an excerpt of the publishers node within a CruiseControl build file.

You should now do some cleanup of temporary files, etc.


Note: Apologies for the images of xml. Blogger chucks a hissy fit if you include xml markup inside a post. What is this? The Nineties?

Monday, April 7, 2008

QuickTest and TeamBuild for Continuous Integration

A while ago Grant posted about integrating QuickTest (QT) into a Team Build continuous integration server. I said I would post about my half of the process. I’ve have been a bit busy of late to organise all my notes and publish this post. However it’s all organised now so, without further stalling for time…

The first part of the process is to ensure that you have a good QuickTest project setup This is what I did and why:


Organisation of Projects
An automated functional testing project (known to QuickTest as a Test) in my opinion should represent a single system. All test cases that actively test this system should be stored in this project. This ensures that our tests are all stored together.

A project should have a name and to simplify the integration with TeamBuild the project should be called “quick-test”. The folder that the quick-test project is in should be named after the Branch in source-control.

Example:
-The test team branch
|-The Name of the System
| |-quick-test

The common naming conventions will help ensure a close correlation between the code that is used to build a system and the automation code used to test it. This is especially relevant if the QT code is in a different branch to the app-code.

Note: Here there were two primary ways to configure the projects within TFS. The first is to put the functional testing code in the same branch as the code that it tests. The unit tests are also in that branch structure and with the code and all related content are together.

The second method is to have a separate branch for the Testing Team and then under each, a folder for each project. For convenience sake we named the sub-folder the same name as the code branch. Under this was our quick-test folder. Load-runner or any other tool that tests this same project would also be stored at this level.

We went with the second method because QT repository files can get quite large and this would have been a problem for the developers on an already strained TFS server. I also understand that workspace mappings may alleviate this problem further. I’m not 100% here as SVN is my source control system of choice (don’t tell Grant).

From an access management perspective, giving testers, who will probably be unfamiliar with the processes around source control, access to only one branch may make their lives simpler.

Even though we went with the second method, I would investigate the first method for your organisation to see if it fits. It’s a better logical structure.


Organisation of Repositories
The repository is where the objects that are used by QuickTest to control your application are stored. There are three levels of repositories:
  • Local – Attached to an asset
  • Project – All objects for a project
  • Global – Merge of all project repositories
I recommend not using a local repository as it is a maintenance nightmare. As you develop your automation test cases, continually push your objects into the project level repository and associate all actions with the project one. It’s much easier to maintain that duplicating objects into each local repository.

Furthermore I don’t recommend using a global repository either. Your objects should relate to the project you are testing. Once again this is primarily a hassle to maintain. If you have dedicated individuals managing the merging of object repositories then go for it. Otherwise give it a miss.

Now, with the current setup, projects are very isolated and it is not possible to write automated scenarios that interact across separate systems. For this I would suggest having a common project that is basically the same as a global repository. The difference being that it only contains the objects needed for cross system test cases are included in this branch. This involves less merging maintenance than merging all objects.

If you require a common repository, put it into a separate branch. This will make it easier for the build script to pull in the common repository when running a continuous integration instance.

The repository should be called repository.tsr in all scenarios. The location of the repository will determine whether it is project, global or common repository. Once again this makes it easier for the build script as it can expect a particular file rather than the name of the file being explicitly configured.


Actions and Quick Test
My definition of actions in QuickTest differs from standard usage. Personally I don’t like their setup and put some rules around when actions should be used. This in my opinion makes their usage cleaner.

An action to QuickTest is a single script that can be executed in isolation. To use, an action will represent either a single test scenario or a reusable test scenario. Scripts can call other actions. However, for the sake of simplicity down the track a script should only call reusable actions.

I’ll define some terminology to make this consistent:

  • Action – a single script that represents a single test case. Like all good test cases it should have single objective. If you are testing more than one thing, write two actions. See my post on the action-test-scenario naming convention for information on succinct naming of test cases and reasons for singular testing scope.
  • Reusable Action – An action in QT that you can be flagged to be “reusable”. To me this should not generate and pass or fail counts. It should merely ensure a state when called.
The first action of a project should be called zzRepository and we can use that to edit and mange our project repository in a local space. This action is deliberately excluded from CI results.

Reusable actions should start with the word ensure. They are required to establish a state on behalf of the calling action (they ensure a state). Once again these actions are not included in the CI results.


Back to Continuous Integration
Once you have set up your structure. Talk with your TFS guy to get the code checked in an in the right format. Once again this link to Grant's work will cover the next step.

In summary: the build script will pull in the launch QT pulling in the repository.tsr. If you use a common repository, pull that in as well. Then pipe in all actions one at a time to execute them.

After the build occurs QT produces a results.xml document. We need to take this and make it look even slightly better than the default QT one to make it useful. I really like the way CruiseControl.NET presents the NUnit xml format. So I wrote a xsl transform to make the QT -> NUnit transform.

Qt2NUnit.xsl

Finally you will need to adjust the CruiseControl
.NET xsl for presenting NUnit xml-docs to reference TeamBuild images. You can use my version here