The Ops Community ⚙️

Cover image for Write devopsish tests using Tomty and Raku
Alexey Melezhik
Alexey Melezhik

Posted on

Write devopsish tests using Tomty and Raku

Tomty is a Raku test framework with focus on devops tasks. Tomty allows one to write test scenarios on Bash (or whatever) and orchestrate them using Raku.

In this post I am going to give a quick introduction into Tomty.


Installation

Tomty is installed as Raku module, using zef - Raku package manager:

zef install --/test https://github.com/melezhik/Sparrow6.git
zef install --/test https://github.com/melezhik/Tomty.git 
Enter fullscreen mode Exit fullscreen mode

We need bleeding edge version of Tomty and Sparrow (dependency for Tomty) to get an access to all the features mentioned in this post.

Setup Tomty

Working with Tomty requires some initialization. First of all we need to create a working directory for tests and initialize it. Optionally we can install Bash completion for tomty - Tomty cli application:

export SP6_REPO=https://sparrowhub.io/repo
mkdir work
cd work
tomty --init
tomty --completion
Enter fullscreen mode Exit fullscreen mode

Create first scenario

Scenarios could be written on many languages, in this post I'll focus on Bash as it's a simple and quite popular scripting language for devops tasks and automation. Tomty allows effectively right low level tasks in Bash while gluing them together with Raku.

A Bash scenario should be just a file named task.bash and located at some directory:

mkdir -p tasks/task1/
nano tasks/task1/task.bash
Enter fullscreen mode Exit fullscreen mode
echo "hello world"
Enter fullscreen mode Exit fullscreen mode

Once bash task is created, we can run it through a Raku wrapper:

tomty --edit my-task
Enter fullscreen mode Exit fullscreen mode
#!raku
task-run "tasks/task1"
Enter fullscreen mode Exit fullscreen mode

In context of Raku a Bash task gets called as a Raku function task-run, with a parameter setting a task directory.

The approach gives us a benefit of using high level language to call low level Bash scenarios.

Now, let's run our first task:

tomty my-task
Enter fullscreen mode Exit fullscreen mode
[repository] :: index updated from file:///root/repo/api/v1/index
[tasks/task1] :: hello world
Enter fullscreen mode Exit fullscreen mode

The task executed successfully, now let's convert this trivial hello world example it into something more practical.

Check if a web site is available

The task of checking an http resource health check is quite common in daily devops @job. Let's see how we could do this in Tomty.

First, let's create a Bash task.

nano tasks/task1/task.bash
Enter fullscreen mode Exit fullscreen mode
curl -s -f $(config url) -o /dev/null -D - | head  -n 4
Enter fullscreen mode Exit fullscreen mode

The task is just using curl command to GET some http URL, pay attention that -f flag causes curl to exit with none zero exit code in case of receiving none successful http response.

A Tomty scenario, would change a bit to pass tested URL as a paramater into a Bash task:

tomty --edit my-task
Enter fullscreen mode Exit fullscreen mode
#!raku
task-run "tasks/task1", %(
  url => "https://raku.org"
);
Enter fullscreen mode Exit fullscreen mode

Now let's see how it works:

tomty my-task
Enter fullscreen mode Exit fullscreen mode
[tasks/task1] :: HTTP/2 200
[tasks/task1] :: date: Fri, 02 Jul 2021 18:20:58 GMT
[tasks/task1] :: content-type: text/html
[tasks/task1] :: last-modified: Tue, 25 May 2021 16:30:03 GMT
Enter fullscreen mode Exit fullscreen mode

As we could see Bash config name is used as function to access named parameters passed to Bash from Raku as a Raku Hash. This semantic works because Tomty is build on top of Sparrow automation tool, that provides all type of such functionality.


Many times, relying on a script exit code to check if a test passes or not works just fine, however sometime one needs to specify expected script output to define a test state.

Let's see how Tomty allows that.

Task checks

Task checks allow define an output a test expects to see in a running script:

nano tasks/task1/task.check
Enter fullscreen mode Exit fullscreen mode
HTTP/2 200
Enter fullscreen mode Exit fullscreen mode

So we check that https://raku.org web server servers HTTP v2 protocol:

tomty my-task
Enter fullscreen mode Exit fullscreen mode
[repository] :: index updated from file:///root/repo/api/v1/index
[tasks/task1] :: HTTP/2 200
[tasks/task1] :: date: Fri, 02 Jul 2021 19:08:34 GMT
[tasks/task1] :: content-type: text/html
[tasks/task1] :: last-modified: Tue, 25 May 2021 16:30:03 GMT
[task check] stdout match <HTTP/2 200> True
Enter fullscreen mode Exit fullscreen mode

And if we want to check against v1 or v2, we can use Raku regular expressions:

nano tasks/task1/task.check
Enter fullscreen mode Exit fullscreen mode
regexp: "HTTP/" 1 || 2 " 200"
Enter fullscreen mode Exit fullscreen mode

Refer to Sparrow task check documentation to get full explanation of the DSL and see more complex examples of validating scripts output.

Tags

Once you have more and more tests you can run all then by using --all parameter of tomty cli:

tomty --all
Enter fullscreen mode Exit fullscreen mode

However when there are too many tests, it's gets really difficult to manage them.

Tags allows to split your tests by multiple groups and run them specifically. It's could extremely useful with a huge tests base.

Let me show a quick simple example using the previous web site check scenario.

Say, we don't want to run our web site availability test if we don't have the internet access on our testing environment.

Let's first add a tag to a Raku scenario:

tomty --edit my-task
Enter fullscreen mode Exit fullscreen mode
#!raku

=begin tomty
%(
  tags => [ 'offline']
)
=end tomty

task-run "tasks/task1", %(
  url => "https://raku.org"
);
Enter fullscreen mode Exit fullscreen mode

As we can see tags added into dedicated "tomty" Pod6 sections as Raku array ( there could be many tags ).

Now let's see how we could use this tag, when running tomty cli:

tomty --skip=offline
Enter fullscreen mode Exit fullscreen mode
[1/1] / [my-task] ....... SKIP
=========================================
(=: / [1] tests in 0 sec / (0) tests passed
Enter fullscreen mode Exit fullscreen mode

As we can see Tomty did not execute the test, as we required to skip any tests tagged as offline

We could have build even more sophisticated examples. For example to run only offline tests for application version 2, but to skip production tests:

tomty --only=offline+app-v2 --skip=production
Enter fullscreen mode Exit fullscreen mode

To list all available tags run:

tomty --list --tags
Enter fullscreen mode Exit fullscreen mode

Sometimes you want only list tests with theirs tags, not execute them, the previous example would be rewritten as:

tomty --tags --only=offline+app-v2 --skip=production
Enter fullscreen mode Exit fullscreen mode

Conclusion

This was a brief introduction into Tomty - test framework written on Raku and supporting many scripting languages to write low level tasks. The main philosophy of Sparrow ( the engine Tomty is built upon ) - use those languages that fits your domain best ( in our case - Bash is simple and efficient way to send http requests) and glue scripts together using high language - Raku, where scripts get called as functions.

When I develop tests for my daily devops tasks on Tomty, I switch between Bash and Raku often and this approach allows me do my work effectively and with minimal efforts.


Thanks for reading. I'd like to hear feedback as usual.

Alexey

Top comments (0)