cucumber/cucumber — Issue #154: WireSupport proposed changes
Author: graza
Created: 2011-10-14 00:26:56+00:00
State: open

Wire protocol implementations that I've seen tend to use wrapper scripts that get the wire server running whilst making a guess at the directories from which to load files in their native language, and then launch Cucumber passing any parameters through. This not only obscures Cucumber, but could cause issues with wrong interpretation of parameters, and hence wrong sets of step definitions being loaded.

I'd like to extend WireSupport in two ways:

1/ To have Cucumber start the wire server itself, and
2/ Allow Cucumber to tell the wire server which step definition files to load.

First: It's fairly easy to get a process to start a child process. It just needs to know what to load. However the current implementation on the Cucumber side uses TCP sockets to make the connection and this isn't great for connecting to child processes; so I propose that Cucumber use Socket.pair to create a Unix domain socket connection prior to spawning the child process. This prevents issues like trying to decide which TCP port should be used, waiting for the child process to listen. (I'm not 100% sure this will work under Windows.)

Second: Cucumber supports being extended to support other languages through modules named with the file extension used by the language. For example, .rb files use the Cucumber::RbSupport module. If a new language was to be implemented as a wire protocol server, a corresponding Cucumber language support module could be based on WireSupport. If the wire protocol was extended to support a load_code_file message, then Cucumber could tell the wire server exactly which files to load for a given test.

I have an implementation of these ideas which borrows heavily from the current WireSupport code: https://gist.github.com/1285897

But this is probably a fairly fragile way to implement language support using the wire protocol because it would break when the Cucumber code changes. Instead I propose a wire protocol module that could be included in a language support module to get access to the wire protocol.

For example, imagining that there's a Cucumber::WireProtocol module for doing this, for a language whose files have the .bacon file extension:

module Cucumber
module BaconSupport
class BaconLanguage
include Cucumber::WireProtocol
def initialize(step_mother)
# start server with connection remembered in @socket
end
attr_reader :socket
end
end
end

When Cucumber is running, the first .bacon file it finds will cause the code above to be loaded and the class to be instantiated. Then all .bacon files will be passed to the object's load_code_file method which will send the message down to the child process for loading.

Comments welcome.

Cheers,
Gra.