Mr Andersson

Integration testing HTTP service caller using PostBin.org

leave a comment »

Problem: Post-Receive service hooks in GitHub are great. However, the lack all kind of flexibility chosing which commiters and/or branch of a repository the service hooks should be applied to. The other end, Hudson CI in this case, of the service hook call has the same problem.
Solution: As many other have, I started out to write a HTTP proxy which could provide some conditional logic for when to proceed with a Post-Receive call.

I started out driving the development of my proxy using TDD. My initial requirement was to NOT proceed with Post-Receive calls for certain commiters. So I started with the following failing end-to-end tests:

[Test]
public void GivenATargetAndAnIgnoredCommiter_WhenPostingPayloadWithCommitsByIgnoredUserOnly_ThenTargetWillNotBeCalled() {}

[Test]
public void GivenATargetAndAnIgnoredCommiter_WhenPostingPayloadWithCommitsWithAMixOfIgnoredAndNotIgnoredUsers_ThenTargetWillBeCalled() {}

After a while of hacking around I ended up with the following tests which tested my needs of the logic in my little service hook proxy:

[Test]
public void GivenATargetAndAnIgnoredCommiter_WhenPostingPayloadWithCommitsByIgnoredUserOnly_ThenTargetWillNotBeCalled()
{
	var postReceiveHook = GivenATargetAndAnIgnoredCommiter();

	Payload payload = PayloadWithCommitsByIgnoredUserOnly();
	postReceiveHook.Post(payload);

	Assert.AreNotEqual( payload, _testTarget.Received );
}

[Test]
public void GivenATargetAndAnIgnoredCommiter_WhenPostingPayloadWithCommitsWithAMixOfIgnoredAndNotIgnoredUsers_ThenTargetWillBeCalled()
{
	var postReceiveHook = GivenATargetAndAnIgnoredCommiter();

	Payload payload = PayloadWithCommitsWithAMixOfIgnoredAndNotIgnoredUsers();
	postReceiveHook.Post(payload);

	Assert.AreEqual( payload, _testTarget.Received );
}

But these tests, are they really end-to-end tests involving a Hudson CI instance?
Let’s take a look at the class behind the _testTarget field:

internal class TestTarget : IPostReceiveTarget
{
	public HttpStatusCode Call( Payload payload )
	{
		Received = payload;
		return HttpStatusCode.OK;
	}

	public Payload Received { get; private set; }
}

I don’t think so!
But do I want to bundle a complete Hudson CI instance with my NUnit test project? No! So where to draw the line?
Let’s try to find out what we actually want here.

  • Is it important to actually verify that the Hudson CI server can process the GitHub Post-Receive Service Hook JSON payload? Nah.
  • Is it important to verify that it can forward requests to different target URLs (Hudson jobs)? Nah.
  • Is it important to verify that it can receive a payload from GitHub and then resend the same payload to an arbitrary HTTP POST target? Yes!

Let’s take a look at the interface I wrote to separate the conditional logic from faking HTTP requests to Hudson CI in the previous tests:

public interface IPostReceiveTarget
{
	HttpStatusCode Call( Payload payload );
}

Right here I felt a bit bored because I started out writing the HTTP POST service call gateway, no tests involved.
Ended up with the following piece:

public class HttpPostTarget : IPostReceiveTarget 
{
	public HttpPostTarget( string targetUrl )
	{
		Url = targetUrl;
	}

	public HttpStatusCode Call( Payload payload )
	{
		var wc = new WebClient {Encoding = Encoding.UTF8};
		wc.Headers.Add( HttpRequestHeader.ContentType, "application/json" );
		try
		{
			wc.UploadString( Url, JsonConvert.SerializeObject( payload ) );
			return HttpStatusCode.OK;
		}
		catch ( WebException ex )
		{
			var response = ex.Response as HttpWebResponse;
			return response == null ? HttpStatusCode.BadRequest : response.StatusCode;
		}
	}

	public string Url { get; private set; }
}

So what do you say? This code can’t be tested? Well, I could go down the road and write a test which utilizes the HttpListener and verify the payload received by the listener in the test. Doable, yes indeed, but earlier today I was wasting some hour or two on getting the HttpListener to work with Windows Firewall (a.k.a. the “netsh” ceremony) which totally failed since I was hosting the code on a network share on my Mac and trying to fire up the listener on the Windows 7 Parallels VM….Aaarghh! Frustration! I just want the simplest possible thing that could work out of the box!

Suddenly I remembered a web hook debug thingy I stumpled upon a couple of months earlier:

  1. Go to www.postbin.org and make a PostBin
  2. Your created PostBin’s URL is shown
  3. Start making HTTP POST requests to that URL
  4. See the result at your PostBin’s URL or access the Atom feed for it (append /feed to the URL)

Excellent!
So what is the most LOC effective and least ugly integration test I can make out of this which tests my HTTP POST code?
Here is what I ended up with:

[TestFixture]
public class HttpPostTargetPostBinTests
{
	[Test]
	public void GivenAPayloadAndAPostBinBucket_WhenCallingTheTarget_ThenPostBinReturnsThePostedPayload()
	{
		const string postBinBucket = "http://www.postbin.org/93483c01";
		var target = new HttpPostTarget( postBinBucket );
		var commitId = new Random().Next().ToString();
		Payload samplePayload = SamplePayload( commitId );
		var status = target.Call( samplePayload );

		var content = GetFirstEntryContentOfAtomFeed( postBinBucket + "/feed" );

		Assert.AreEqual( HttpStatusCode.OK, status );
		StringAssert.Contains( """ + commitId + """, content );
	}

	static string GetFirstEntryContentOfAtomFeed( string atomUrl )
	{
		XNamespace atom = "http://www.w3.org/2005/Atom"; 
		return XDocument.Load( atomUrl ).Descendants( atom + "content" ).First().Value;
	}

	private Payload SamplePayload( string commitId )
	{
		return new Payload { Commits = new[] { new Commit { Id = commitId, Author = new Author { Email = "foo@bar.tm", Name = "Foo Bar" } } } };
	}
}

Someone else can probably make it prettier and more effective but this just works out of the box, without adding any external library references except for NUnit.

Conclusion:
It is very easy to get into trouble when writing tests for problems which are closely tied up with or depending on some technical concepts. In my case I was trying to get away as far as possible from a data format (JSON) and a network protocol (HTTP). A good start seems to be to make the abstractions where you hit these techie stuff. Think of that before you find yourself extending the problem context; Do you really need that infrastructure or external library to deal with your current design issues? Stay in context. When time comes and you need to hit the outer limit of the context, proceed as always: Make the simplest possible thing that could work.

Note:
PostBin is a web site made by Jeff Lindsay. You can fork his work on GitHub.

Written by anderssonjohan

July 19, 2011 at 09:20

Posted in programming

Tagged with , , , ,

Median Nerve Entrapment

leave a comment »

MEDICAL DISCLAIMER: The following information is my personal notes about PTS. It is intended for informational purposes only. Consult a physician to help you diagnose and treat injuries of any kind.

In my last post I wrote about something called Pronator Teres Syndrome (PTS or just Pronator Syndrome). So what is this fuzz about? Who is this Pronator Teres guy and why is he bothering me?
When you are seeing a doctor he/she will use a lots of words that you probably doesn’t understand and can’t refer to. So after seeing the doctor you search the web to find more about these new words. In this blog post I will try sort out some of the words/sounds I learned so far which relates to PTS.

Release your hands from your computer for a while and look at your palm, also known as the volar side. Now turn your hands 180 degrees so your palms face down. What you just did is called pronation.

I found this great illustration at TheFreeDictionary.com which also shows the opposite act of pronation, which is called supination:

Illustration: Pronation and supination

Mosby’s Dictionary of Complementary and Alternative Medicine. (c) 2005, Elsevier.

So to get back where I started; Pronator Teres is a muscle in the forearm which makes the arm pronate:

Pronator Teres Muscle
APMSurgery.com

The median nerve can be entrapped at several sites in the forearm. Most common seems to be the carpal tunnel syndrome (carpal = wrist), CTS. More uncommon is the pronator teres syndrome, or PTS, which is caused by hypertrophy in the muscle.

When a nerve is entrapped you get parasthesia and in the case of PTS, pain occurs in the palm at the thumb and at the elbow (more specifically at the pronator teres muscle).
Pronator Teres Pain
Pain can also be present in other parts of the arm with PTS present. These muscles are overused because of compensation for the decreased capacity of signals to the lower arm in the median nerve.
This decreasion can easily be discovered by a orthopedic specialist by using different algorithms during a manual examination of the arm. As far as I have understood (I’m not a M.D.) these algorithms are built up as decision trees consisting of several manual tests. Each “exit point” of these algorithms indicates different diagnoses.
During my search for information about PTS I found a great book named Functional Soft-Tissue Examination and Treatment by Manual Methods by Warren Hammer.
A more common diagnose caused by median nerve entrapment in the fore arm are the Carpal Tunnel Syndrome, CTS.

Nucleus Medical Media has a pretty good illustration covering some of the surgical incisions used when treating CTS and PTS.

Treatment for PTS includes, but is not limited to, massage, pain killers and surgical treatment. As I have been told – also nerve glide excercises have shown good results in some cases.
For people spending most of the day at a desk/computer, ergonomic planning of the workplace is a must!
Tips and checklists: Physical Therapy: Ergonomics and preventing work injuries

More reading:

Written by anderssonjohan

March 7, 2011 at 07:00

Posted in life

Pronator Teres Syndrome

leave a comment »

Since the end of november last year I have been struggling (rather “whining about”, if you ask my fiancee!) with pain in my forearms, primarily in the right arm (my non-dominant arm since I’m left-handed). Thanks to the great folks (Camilla and Elisabet) at http://www.handfootsurgery.com I now know this is caused by something called “Pronator Teres Syndrome” (swedish: pronatorsyndrom), a repetitive strain injury. (read about it here).

I’m currently seeking around the net to get as much (relevant) information I can about this injury.
Please let me know if you have some for me, or if you have been treated for PTS.

You can find the information I’ve been reading so far in this link collection.

Written by anderssonjohan

February 2, 2011 at 15:51

Posted in life

WordWrap function in c#

leave a comment »

Today I worked on a piece of code at RemoteX and needed a pretty simple word wrapping function in C# which:
1) breaks between words, if possible
2) breaks words, if they’re too long to fit on one line

I used the almighty code snippet resource but couldn’t find a quick fix for my need without digging further into the different solutions, so here is my contribution to the long list of word-wrapping functions posted around the web.
Just like I tried to use several of the code snippets I found on the web, you are free to use mine.

I take no responsibility for any bugs you may find in this code snippet may include. Please let the tests guide you!

https://github.com/anderssonjohan/snippets/blob/master/wordwrap/WordWrapTests.cs

Written by anderssonjohan

November 3, 2010 at 12:51

Posted in programming

Tagged with ,

The move to WordPress.com

leave a comment »

I have recently moved this blog from Blogger.com to WordPress.com. Everything have went fine, using the Import tools in the WordPress blog dashboard. The only thing which didn’t work out out-of-the-box was source code syntax highlighting. Previously I used FTP publishing with Blogger.com and I used Alex Gorbachev’s syntax highlighter from my own server. To fix this small issue I needed to edit all posts depending on the syntax highlighter using the WordPress.com syntax.

Please do report any issues with the blog. :)

Written by anderssonjohan

June 28, 2010 at 22:23

Posted in misc

Deploying applications to Windows and Windows Phones which supports dynamic modules

leave a comment »

Many .Net applications being developed today are leveraging the greatness of dependency injection using some sort of inversion of control-container. So do we at RemoteX when we develop the product called RemoteX Applications. The product has two client applications which roughly adresses the same use cases. One is targeting desktop computers and the other one is targeting Windows Phone (you can read more here and here).

As you can tell by the name, the product consists of several applications (or rather modules). Using frameworks like Prism or Caliburn we can, in code, easily manage each part of the product. And the deployment is taken care of using ClickOnce technology using mage.exe (the MAnifest GEnerator).
But that’s for the desktop client targeting WPF.

So the big question is, how are we going mobile with this?

What regards an inversion of control-container we are “almost there”. We have a home-grown container in place which have been around for a while now, even though it lacks some basic features you would expect an ioc container of year MMX to have.
Speaking of deployment to the Windows Phone you probably know you are kind of locked to using CABinet files. If you are using the tools Microsoft brought to us, you probably also use their Device Setup projects in Visual Studio.
They are good, but you must use Visual Studio to choose the contents of and create/build your CAB file.
What this basically means is that we need to use devenv.exe to build each customer’s customized CAB file.
So up til now we have not had per customer customized CAB files.

All I wanted was ClickOnce technology and a manifest generator for the Windows Phone. So what’s the solution on that?
Say hello to the PowerShell script New-CabWizInf.ps1:

.\New-CabWizInf.ps1 -path .\myapp.inf -appName “My Application” -manufacturer “RemoteX” -fromDirectory .\MyApplication\bin\Release

It works like mage.exe with its -fromDirectory switch and creates the necessary .inf-file (like an Visual Studio Device Setup project would). All needed from that point is to call CABWIZ.exe and Set-AuthenticodeSignature in PowerShell to create and sign the CAB file.
The real power is the -fromDirectory switch which allows us to create custom CAB files on the fly.

So here is a peek of what our setup package scripts now looks like:

Setup Package for Windows using ClickOnce
mage -new deployment -tofile MyApp.application -fromdirectory bin\Release -name “My App” -publisher “RemoteX”
mage -sign

Setup Package for Windows Phones using CAB files
.\New-CabWizInf.ps1 -path MyApp.inf -fromDirectory bin\Release -appName “My App” -manufacturer “RemoteX”
cabwiz MyApp.inf /dest .\
Set-AuthenticodeSignature .\MyApp.CAB

So right now I’m a very happy camper since our packaging tools for Windows AND Windows Phone have equal capabilities which allows us to use dependency injection with dynamic module selection.

Next stop, Prism and Silverlight for the Windows Phone?

Written by anderssonjohan

January 20, 2010 at 23:28

Posted in software

Tagged with , , , , ,

How to get $VerbosePreference applied on remote commands

leave a comment »

If you use Write-Verbose in a script executed on a remote computer, you may not get the result you expect.

Example TestRemoteCommand.ps1:

Invoke-Command -ComputerName comp1 -ScriptBlock { 
    Write-Host "hello"
    Write-Verbose "there"
}

The above will only output “hello” and not “there” in the host window.

I thought I was clever by just passing along the $VerbosePreference value:

Invoke-Command -ComputerName comp1 -ArgumentList $VerbosePreference -ScriptBlock { 
    param( $VerbosePreference )
    Write-Host "hello"
    Write-Verbose "there"
}

But, still no luck! Only the statement using Write-Host is included in the output when the command is invoked on the remote computer.
What’s going on here is that the argument sent to the remotely executed script block is converted to an integer, which is the base integral type of the underlying enum type of $VerbosePreference.
So I figured that typing the argument in the param() clause will bind the parameter to the correct data type, and voila, it now works as expected.

Invoke-Command -ComputerName comp1 -ArgumentList $VerbosePreference -ScriptBlock { 
    param( [System.Management.Automation.ActionPreference] $VerbosePreference )
    Write-Host "hello"
    Write-Verbose "there"
}

Now you can toggle the verbose output of your remote script using the switch of your local script:

.\TestRemoteCommand.ps1 # Default, or -Verbose:$false
.\TestRemoteCommand.ps1 -Verbose

Written by anderssonjohan

November 19, 2009 at 14:25

Posted in scripting

Tagged with ,

Follow

Get every new post delivered to your Inbox.