In Progress
Unit 1, Lesson 1
In Progress

Gem Love Part 5

Video transcript & code

Back in Episode 69, I completed a rudimentary GemLove server to complement the command-line client. I have tests for both the client and the server. But before I go any further I'd really like to have at least a basic test that exercises both the client and server together, and verifies that they can talk to each other without issues.

I already have one high-level acceptance test which is intended to do just that. But when I last looked at it I had pended it out because I didn't yet have a server for the client to talk to. Now that I have a server, it's time to reenable this test and make it pass.

specify 'endorsing a gem' do
  stub_request(:any, /^www\.gemlove\.org/).to_rack(GemLove::Server)
  run 'gem love fattr'
  gem_named('fattr').should have(1).endorsements
end

There are many different ways to test a client's integration with a server. The choice of how to test often boils down to how much control we have over both sides of the connection. If the server were being built by another team or by a third party vendor, I might have to settle for testing the integration manually, or using some kind of faked-up version of the server.

But in this case I control both sides of the connection, so I have more options. One route I could go would be to start up a server process, either manually or as part of the test setup, and test the client against this process. This is probably the most realistic testing environment I could hope for.

But testing with multiple processes is finicky and prone to error. I'd like to avoid it, at least for now. Instead, I add the webmock library to my acceptance test, and I add an instruction to capture requests to the Gem-Love server. But instead of using webmock to construct a fake server, I instead tell it to use the real server class to handle all requests.

specify 'endorsing a gem' do
  stub_request(:any, /^www\.gemlove\.org/).to_rack(GemLove::Server)
  run 'gem love fattr'
  gem_named('fattr').should have(1).endorsements
end

Remember that the server class is a rack application. WebMock's #to_rack method can use any rack app to respond to captured web requests. The net result is that I'm plugging the real client into the real server, and only faking out the HTTP connection between them.

I run the tests, and lo and behold, they all pass.

To be honest, this feels a little too good to be true. Not that the tests pass, since the code is simple enough so far. But that I can test the client against the server without starting up separate processes.

Perhaps as the application grows and my testing needs become more complex, I'll feel the need to set up the acceptance tests in a more realistic configuration, with the server running in its own process and accepting actual HTTP connections. But for now, I'm not going to complain. I have validation that the client and server communicate, and the tests have none of the slowness or flakiness I associate with multi-process testing. This definitely makes me a happy hacker!

Responses