Write devopsish tests using Tomty and Raku
Tags: devops, raku, bash, testing
Published: 2021-07-04 23:42:17

---
title: Write devopsish tests using Tomty and Raku
published: true
description: How to write devops tests using Tomty framework
tags: devops, Raku, Bash, testing
cover_image: https://publicdomainvectors.org/photos/Hearts-Butterfly.png
---

[Tomty](https://github.com/melezhik/Tomty) is a Raku test framework with focus on devops tasks. Tomty allows one to write test scenarios on Bash (or [whatever](https://github.com/melezhik/Sparrow6#supported-languages)) 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:
 
```bash
zef install --/test https://github.com/melezhik/Sparrow6.git
zef install --/test https://github.com/melezhik/Tomty.git 
```

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:

```bash
export SP6_REPO=https://sparrowhub.io/repo
mkdir work
cd work
tomty --init
tomty --completion
```

# 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:

```bash
mkdir -p tasks/task1/
nano tasks/task1/task.bash
```

```bash
echo "hello world"
```
Once bash task is created, we can run it through a Raku wrapper:

```bash
tomty --edit my-task
```

```raku
#!raku
task-run "tasks/task1"
```

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:

```bash
tomty my-task
```

```log
[repository] :: index updated from file:///root/repo/api/v1/index
[tasks/task1] :: hello world
```

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. 


```bash
nano tasks/task1/task.bash
```

```bash
curl -s -f $(config url) -o /dev/null -D - | head  -n 4
```

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:

```bash
tomty --edit my-task
```

```raku
#!raku
task-run "tasks/task1", %(
  url => "https://raku.org"
);
```

Now let's see how it works:

```bash
tomty my-task
```

```log
[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
```

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:

```bash
nano tasks/task1/task.check
```

```log
HTTP/2 200
```

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

```bash
tomty my-task
```

```log
[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
```

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

```bash
nano tasks/task1/task.check
```

```log
regexp: "HTTP/" 1 || 2 " 200"
```

Refer to Sparrow [task check](https://github.com/melezhik/Sparrow6/blob/master/documentation/taskchecks.md) 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:

```bash
tomty --all
```

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:

```bash
tomty --edit my-task
```

```raku
#!raku

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

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

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:

```bash
tomty --skip=offline
```

```log
[1/1] / [my-task] ....... SKIP
=========================================
(=: / [1] tests in 0 sec / (0) tests passed
```

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
```

To list all available tags run:

```bash
tomty --list --tags
```

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

```bash
tomty --tags --only=offline+app-v2 --skip=production
```

# 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