YAML primer


Introduction

YAML is a human-friendly data representation format who’s main design goals are simplicity and readability. You can think about YAML as JSON without the ugly parts. Because of its ease of use, YAML is being adopted by more and more projects every day for storing configuration files and other types of structured data that is meant to be edited by hand.

This page is not intended as a comprehensive guide on YAML, and focuses on the aspects that are most relevant in the context of OpenTest.

YAML best practices

  • Never use TAB characters for indentation or any other purpose. Only use SPACE characters. Most decent editors behave like that by default or can be configured to do so.

  • Always use a monospaced font to view and edit YAML, so it’s easy to spot indentation errors.

  • Save YAML files in the UTF-8 encoding. This is also something that is normally handled automatically by most good editors.

Tip
One of the best text editors we’ve seen so far, that is free and open source, with an awesome community around it, is Visual Studio Code. We highly recommend it.

Objects and hierarchical data

Just like JSON, YAML stores objects as a collection of key and value pairs, for example:

name: Joe
age: 35

The above data, is an object with two properties: name and age. The same data structure, if you were to write it in JSON, would look like this:

{
    "name": "Joe",
    "age": 35
}

It should be pretty obvious why YAML is the better format when humans are involved: no unnecessary curly braces, commas and double-quotes to slow us down.

Tip
JSON data is valid YAML data. Yes, you heard that right. YAML is very forgiving and flexible in the way you can write your data and YAML parsers can understand JSON data just fine. The nice side-effect is that you can copy and paste sections of JSON data files into your YAML data files with no extra work required.

So what if the value of a property is an object itself? For example, let say we want to add an address property for the person object we defined above. The address should be represented as an object with two properties: streetAddress and city. This is how the YAML data looks now:

name: Joe
age: 35
address:
  streetAddress: 123 No Street
  city: Phantom City

As you can see, indentation is what dictates hierarchy in YAML. Both the streetAddress and city properties are indented at exactly two spaces from the left. This means they are both properties of the same object. This object represents the value of the address property.

Here’s what the corresponding JSON would look like:

{
    "name": "Joe",
    "age": 35,
    "address": {
        "streetAddress": "123 No Street",
        "city": "Phantom City"
    }
}
Tip
Make sure to always have at least one space after the ':' (colon) character when specifying property values. For example, name: Joe is valid syntax, whereas name:Joe is not.

Primitive data types

YAML supports the same core types as JSON: string, number, boolean, null. Examples:

name: Fred
age: 36
employed: true
siblings: null

String quoting

While YAML allows string values to be specified without quotes, there are a few scenarios that do require quoting your strings:

  • Providing a numeric value that we want interpreted as a string instead of a number.

    storeNumber: "123"
  • Strings containing special characters (:, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, @, \).

    xpath: "//android.widget.TextView[@text='Submit']"
  • Strings containing escape sequences that need to be parsed as such.

    streetAddress: "123 No Street\nPhantom City"
Tip
When a string value behaves in ways you didn’t expect, try using double quotes.

Multiline strings

There are two ways to provide multiline strings in YAML:

  • Literal style, using the | (pipe) character, which preserves end-of-line characters. This is especially useful when defining script actions:

    - script: |
        for (var buttonNo = 1; buttonNo <= 100; buttonNo++) {
            $runAction("org.getopentest.selenium.Click", {
                locator: { id: "button" + buttonNo }
            });
        }
  • Folded style, using the > (greater then) character, which removes end of line characters and replaces double end of lines with single ones. This can be used for test descriptions or test action descriptions:

    - description: >
        This is a longer action description which spans several lines,
        which will conveniently be transformed by the YAML parser into
        a string with no end of line characters.

Arrays

Let’s consider the following JSON data:

{
    "names": ["name 1", "name 2", "name 3"]
}

This is how the same data can be written in YAML:

names:
    - name 1
    - name 2
    - name 3

Each new array element is defined using a - (dash) character, followed by a space.

We can also use the abbreviated form:

names: [name 1, name 2, name 3]

And this is how you can define an array of two objects:

- name: Fred
  age: 36

- name: Wilma
  age: 28

Notice how the names of the properties have to be aligned horizontally. The data structure above can also be written in abbreviated form:

[ {name: Fred, age: 36}, {name: Wilma, age: 28} ]

And, finally, an example of real OpenTest syntax:

actions:
    - action: org.getopentest.selenium.NavigateTo
      args:
        url: https://github.com

    - action: org.getopentest.selenium.AssertElementVisible
      args:
        locator: { xpath: "//a[@href='/facebook/react']" }

which is equivalent to this JSON:

{
    "actions": [
        {
            "action": "org.getopentest.selenium.NavigateTo",
            "args": {
                "url": "https://github.com"
            }
        }, {
            "action": "org.getopentest.selenium.AssertElementVisible",
            "args": {
                "locator": {
                    "xpath": "//a[@href='/facebook/react']"
                }
            }
        }
    ]
}

Comment syntax

You can comment a YAML line by using the # (hash) character. Everything after the hash character is a comment:

# This is a YAML comment on its own line
property: value # But this is a comment, too