Authoring a language runner for Gauge

Kashish Munjal
Gauge
5 min readApr 26, 2017

--

Gauge is a light-weight cross-platform test automation tool with the ability to author test cases in the business language. It has a modular architecture with plugins support. There are three types of plugins in Gauge

  • Language
  • IDE
  • Reporting

In this blog, I will try to explain the purpose of a language plugin/runner and how to write one.

What is a Language Runner?

Language Runner is a plugin which lets you write test code implementations in a specific programming language.

There are two phases in the life cycle of a language runner:

Initialization

  • Initialize the project with the language-specific skeleton file.

Execution

  • Execute hooks (when requested by Gauge core).
  • Execute method corresponding to a step and send execution response back to Gauge.
  • Send custom report messages to Gauge.
  • Read/write to datastore (currently, datastore is intra-process, hence parallel processes cannot use a shared datastore).

This post will help you write a basic Python language runner which supports initialization and step execution. Let’s call it “mypython”, so that our tutorial code does not conflict with Gauge’s Python language runner. By the end of this article, will be able to use it through Gauge to create a new project and run specifications, like this:

gauge --init mypython
gauge specs

Configuring your project

Requirements

For writing a language runner, you will need:

  • Gauge installed and available on the PATH.
  • Installation of the programming language that you writing the language runner in (Python in this case).
  • A version control system. Preferably, git.
  • A text editor or IDE of your choice.
  • Familiarity with the programming language that you writing the language runner in.

Getting Started

Create a directory in called “mypython” and create these files and sub-directories in it:

mypython 
|
|--- mypython.json
|
|--- README.md
|
|--- step_impl/
| |--- __init__.py
| |--- step_impl.py
|
|--- getgauge/
| |--- __init__.py
| |--- messages/
| |--- __init__.py
|
|--- start.py

We recommend you use a version control system, preferably git, so that we can track changes and add dependencies from other repositories as we go ahead.

Runner’s metadata file

Every language runner needs to have a <runner_id>.json file, which contains the metadata for the language runner. For an example, see the mypython.json file in the mypython language runner.

<runner_name>.json file serves the following three primary functions:

  • Plugin name, description, version are specified in this file.
  • The properties “init” and “run” in this file are used to specify initialize and run commands for different platforms. For example: while initializing a Gauge project, Gauge will execute the command present in init section of the JSON file.
  • Minimum and maximum Gauge version support are specified here.

README.md

README.md file in the root of this project contains the user and technical documentation, although this is not a requirement.

For an example, see README.md from the JavaScript and Python language runner.

Skeleton files

Each language runner should come with a sample implementation file that can be used as a quick-start for creating a new project.

Put the following content to step_impl/step_impl.py.

Initializing project

When you run this command, Gauge will ask the language runner to copy implementation specific skeleton files in the project directory. Gauge will run the command which is present in the init section in mypython.json file

Put the following content in the start.py and provide execute permission to the file.

chmod +x start.py

This will copy the skeleton files to the user’s project directory which is present in an environment variable GAUGE_PROJECT_ROOT.

Protocol Buffers:

Communication between Gauge and Language Runner happens via TCP using Protocol Buffers.

To communicate with Gauge, there are different request/response messages are configured in the gauge-proto repository. Let’s add the gauge-proto repository as a git submodule to our language runner.

git submodule add https://github.com/getgauge/gauge-proto.git

Create getgauge/messages directory. In this directory, we will put the python code which is generated from the proto files present in the submodule.

cd gauge-protoprotoc --python_out=../getgauge/messages/ spec.proto
protoc --python_out=../getgauge/messages/ messages.proto
cd ../

Execution:

Let’s define a step function which will be used as a decorator in the step implementation. Create getgauge/python.py with the following function definition.

The above decorator will be used to define step implementation in the following way.

see registry.py for more information on storing the implementation and step text.

Gauge opens up a port for protobuf communication and runner connects to the socket by reading the environment variable GAUGE_INTERNAL_PORT.

Now the language runner needs to send responses to the requests sent by Gauge. To read the request and send the response, language runner needs to use socket. (See connection.py for socket communication code). The detailed documentation for every request/response is explained here.

Copy registry.py and connection.py to getgauge directory.

Create getgauge/processor.py and put the following code in it. This will wait for requests and sends respective responses till kill request is received.

Before executing steps, Gauge sends a request to check if the implementation for the given steps are present or not. _validate_step will check in the registry, it will set is_valid to True if present otherwise False.

After validating steps, Gauge will send requests to execute steps, a request will contain parameters and implementation function is called with those parameters. It will send the response back with the result(failed, error, stack trace, type, execution time).

After execution is complete Gauge will send a kill request to language runner and runner needs to close the socket and end the program.

Install & Test:

There are two ways to install the plugin

  • Copy the content of your project to Gauge plugins path i.e %APPDATA%\gauge\plugins\mypython\0.0.1 for Windows and $HOME/.gauge/plugins/mypython/0.0.1 for Mac and Linux.
  • Create a zip file of your project and install it using gauge --install mypython -f <path to zip file>.

The output of gauge -v will contain mypython plugin with version 0.0.1.

After this, you should be able to initialize and execute a Python Gauge project.

gauge --init mypython
gauge specs

Next Steps

In this article, you have seen how to write a basic language runner for Gauge and start executing steps. A language runner can do a lot more. Take a look at the feature matrix of language runners for an overall idea of the current state of language runners for Gauge.

Gauge is an open-source project and is driven by contributions from its growing community. If you do not find a language runner in your favorite language, start writing one!

Resources

--

--