# Assertions

A test is considered passing if the array MVT.ERRORS is empty. MVT.ERRORS is available to you as a common variable. You can manually add errors to this array, but the best way to do this is to run the assert helpers. These make writing tests quick, they format the error nicely and they make the test easier to read.

I’ve written these assertion helpers because I’ve needed them. There are many more that could be added in the future.

# ASSERT.EQUALS

ASSERT.EQUALS(ACTUAL.VALUE, EXPECTED.VALUE)

Assert that the actual value is the same as the expected value.

# ASSERT.NOT.EQUALS

ASSERT.NOT.EQUALS(ACTUAL.VALUE, EXPECTED.VALUE)

Assert that the actual value is NOT the same as the expected value.

# ASSERT.HAS.ERROR

ASSERT.HAS.ERROR(ERROR, ERRORS)

Search for an error message in the errors. ERROR should be the string of what the error should include. Wildcards will automatically be added to both sides of the string. ERRORS is a field-value array of the errors that were returned.

# ASSERT.MISSING.ERROR

ASSERT.MISSING.ERROR(ERROR, ERRORS)

Assert that an error message does not exist in the errors. ERROR should be the string of what the error should include. Wildcards will automatically be added to both sides of the string. ERRORS is a field-value array of the errors that were returned.

# ASSERT.DATABASE.HAS

ASSERT.DATABASE.HAS(FILE.NAME, RECORD.ID)

Assert that the RECORD.ID does exists in the FILE.NAME.

# ASSERT.DATABASE.MISSING

ASSERT.DATABASE.MISSING(FILE.NAME, RECORD.ID)

Assert that the RECORD.ID does NOT exists in the FILE.NAME.

# ASSERT.TRUE

ASSERT.TRUE(VALUE)

Assert that VALUE is truthy (not empty and not 0)

# ASSERT.FALSE

ASSERT.FALSE(VALUE)

Assert that VALUE is false (empty or 0)

# ASSERT.MAIL.SENT

ASSERT.MAIL.SENT(SENT.TIME, SUBJECT, TO.EMAIL, FROM.EMAIL)

Check if an email was sent.

This will check MAIL.HIST to find an email that was sent after SENT.TIME. So before calling the program that you are testing, your test should grab the time.

TEST.SOMETHING:
    SENT.TIME = TIME()
    CALL SOME.SUB
    ASSERT.MAIL.SENT(SENT.TIME, "subject", "to@example.com", "from@example.com")
    RETURN

# ASSERT.MAIL.NOT.SENT

ASSERT.MAIL.NOT.SENT(SENT.TIME, SUBJECT, TO.EMAIL, FROM.EMAIL)

Check if an email was not sent.

This will check MAIL.HIST to find an email that was sent after SENT.TIME. So before calling the program that you are testing, your test should grab the time.

TEST.SOMETHING:
    SENT.TIME = TIME()
    CALL SOME.SUB
    ASSERT.MAIL.NOT.SENT(SENT.TIME, "subject", "to@example.com", "from@example.com")
    RETURN

# ASSERT.JSON.HAS

ASSERT.JSON.HAS(JSON, PROPERTY, VALUE)

Checks a JSON string to see if it has a property with a value. The value needs to be an exact match.

When passing in JSON, ensure that it is in quotes. An easy way to do this in Universe is QUOTE(JSON).

The PROPERTY uses dot notation. For example, given you pass this JSON:

{
    "order": {
        "poNumber": "1234",
        "customer": "abc",
        "lines": [
            {
                "product": "Hue",
                "quantity": "100"
            },
            {
                "product": "Annadale",
                "quantity": "300"
            },
        ]
    }
}

Here are some of the assertions you could make.

ASSERT.JSON.HAS(JSON, "order.customer", "abc")
ASSERT.JSON.HAS(JSON, "order.lines.1.product", "Hue")
ASSERT.JSON.HAS(JSON, "order.lines.2.quantity", "300")

# ASSERT.JSON.CONTAINS

ASSERT.JSON.CONTAINS(JSON, PROPERTY, VALUE)

Checks a JSON string to see if it has a property with a substring. The value does not need to be exact. It can be a partial value.

When passing in JSON, ensure that it is in quotes. An easy way to do this in Universe is QUOTE(JSON).

The PROPERTY uses dot notation. For example, given you pass this JSON:

{
    "order": {
        "poNumber": "1234",
        "customer": "abc",
        "lines": [
            {
                "product": "Hue",
                "quantity": "100"
            },
            {
                "product": "Annadale",
                "quantity": "300"
            },
        ]
    }
}

Here are some of the assertions you could make.

ASSERT.JSON.CONTAINS(JSON, "order.customer", "bc")
ASSERT.JSON.CONTAINS(JSON, "order.lines.2.product", "Anna")

# ASSERT.JSON.HAS.PROPERTY

ASSERT.JSON.HAS.PROPERTY(JSON, PROPERTY, FOUND.VALUE)

Checks a JSON string to see if it has a property. If it does, then it returns the value of the property.

When passing in JSON, ensure that it is in quotes. An easy way to do this in Universe is QUOTE(JSON).

The PROPERTY uses dot notation. For example, given you pass this JSON:

{
    "order": {
        "poNumber": "1234",
        "customer": "abc",
        "lines": [
            {
                "product": "Hue",
                "quantity": "100"
            },
            {
                "product": "Annadale",
                "quantity": "300"
            },
        ]
    }
}

The FOUND.VALUE is an OUT variable which means it will be set to the value of that property. You can use this for further testing.

Here are some of the assertions you could make.

ASSERT.JSON.HAS.PROPERTY(JSON, "order.customer", CUST.NAME)

In the example above, CUST.NAME will be set to abc

# ASSERT.JSON.COUNT

ASSERT.JSON.COUNT(JSON, PROPERTY, VALUE)

Assert that an array in a JSON property has a certain amount of items.

When passing in JSON, ensure that it is in quotes. An easy way to do this in Universe is QUOTE(JSON).

The PROPERTY uses dot notation. For example, given you pass this JSON:

{
    "order": {
        "poNumber": "1234",
        "customer": "abc",
        "lines": [
            {
                "product": "Hue",
                "quantity": "100"
            },
            {
                "product": "Annadale",
                "quantity": "300"
            },
        ]
    }
}

You could then make the following assertion:

ASSERT.JSON.COUNT(JSON, "order.lines", 2)

# ASSERT.JSON.ARRAY.HAS

ASSERT.JSON.ARRAY.HAS(JSON, ARRAY.PATH, SEARCH.PROPERTY, VALUE, FOUND.INDEX)

Searches a JSON string for an array that has a matching property and value.

When passing in JSON, ensure that it is in quotes. An easy way to do this in Universe is QUOTE(JSON).

SEARCH.PROPERTY is the name of the property in the array you are trying to match. This assumes you are searching an array of objects. If you are searching an array of strings then leave this variable blank.

VALUE is the value of the SEARCH.PROPERTY in the array that you are trying to match.

FOUND.INDEX is the index location of matching object or string. This is an OUT value and can be used to do further testing on the object.

ARRAY.PATH is the path to the array you want to search. It uses dot notation. For example, given you pass this JSON:

{
    "order": {
        "poNumber": "1234",
        "customer": "abc",
        "lines": [
            {
                "product": "Hue",
                "quantity": "100"
            },
            {
                "product": "Annadale",
                "quantity": "300"
            },
        ]
    }
}

You could then make the following assertion:

ASSERT.JSON.ARRAY.HAS(JSON, "order.lines", "product", "Hue", FOUND.PRODUCT)

In the example above, FOUND.PRODUCT will be set to 1. So now you could do more assertions like:

ASSERT.JSON.HAS(JSON, "order.lines.":FOUND.PRODUCT:".quantity", 100)

# ASSERT.JSON.ARRAY.MISSING

ASSERT.JSON.ARRAY.HAS(JSON, ARRAY.PATH, SEARCH.PROPERTY, VALUE)

Searches a JSON string for an array that has a matching property and value and asserts that it does not exist in the array.

When passing in JSON, ensure that it is in quotes. An easy way to do this in Universe is QUOTE(JSON).

SEARCH.PROPERTY is the name of the property in the array you are trying to match. This assumes you are searching an array of objects. If you are searching an array of strings then leave this variable blank.

VALUE is the value of the SEARCH.PROPERTY in the array that you are trying to match.

ARRAY.PATH is the path to the array you want to search. It uses dot notation. For example, given you pass this JSON:

{
    "order": {
        "poNumber": "1234",
        "customer": "abc",
        "lines": [
            {
                "product": "Hue",
                "quantity": "100"
            },
            {
                "product": "Annadale",
                "quantity": "300"
            },
        ]
    }
}

You could then make the following assertion:

ASSERT.JSON.ARRAY.MISSING(JSON, "order.lines", "product", "Woolie")

# ASSERT.JSON.ARRAY.HAS.PROPERTY

ASSERT.JSON.ARRAY.HAS.PROPERTY(JSON, ARRAY.PATH, SEARCH.PROPERTY, FOUND.VALUE)

Searches a JSON string for an array that has a matching property. If found, it will set the FOUND.VALUE so you can use it for further testing. This is helpful for when you don't know what the value will be. Examples could be calculations like totals. Another example is a timestamp.

When passing in JSON, ensure that it is in quotes. An easy way to do this in Universe is QUOTE(JSON).

SEARCH.PROPERTY is the name of the property in the array you are trying to match.

FOUND.VALUE is the value of matching property. This is an OUT value and can be used to do further testing on the value.

ARRAY.PATH is the path to the array you want to search. It uses dot notation. For example, given you pass this JSON:

{
    "order": {
        "poNumber": "1234",
        "customer": "abc",
        "lines": [
            {
                "product": "Hue",
                "quantity": "100"
            },
            {
                "product": "Annadale",
                "quantity": "300"
            },
        ]
    }
}

You could then make the following assertion:

ASSERT.JSON.ARRAY.HAS.PROPERTY(JSON, "order.lines", "quantity", FOUND.QUANTITY)

In the example above, FOUND.QUANTITY will be set to 100. So now you could do more assertions like:

ASSERT.TRUE(FOUND.QUANTITY GT 100)

# ASSERT.HAS.JSON.ERRORS

ASSERT.HAS.JSON.ERRORS(JSON, FIELD.NAME, ERROR.VALUE)

This searches a JSON string that contains an error on a specific field.

This assumes your JSON will have this structure:

{
  "errors": [
    {
      "field": "someField",
      "value": "some error message"
    }

  ]
}

When passing in JSON, ensure that it is in quotes. An easy way to do this in Universe is QUOTE(JSON).

FIELD.NAME is the name of the field in the field property of the error object you are searching for.

ERROR.VALUE is the error message that corresponds to the FIELD.NAME that you are searching for. This does not have to be the full error message but can just be a substring.

For example, given you pass this JSON:

{
    "errors": [
      {
        "field": "customerName",
        "value": "Must be at least 3 characters"
      },
      {
        "field": "phone",
        "value": "Invalid phone syntax"
      }
    ]
}

You could then make the following assertion:

ASSERT.HAS.JSON.ERRORS(JSON, "phone", "Invalid phone")

# ASSERT.MISSING.JSON.ERRORS

ASSERT.MISSING.JSON.ERRORS(JSON, FIELD.NAME, ERROR.VALUE)

This searches a JSON string that contains an error on a specific field and asserts that it does not exist.

This assumes your JSON will have this structure:

{
  "errors": [
    {
      "field": "someField",
      "value": "some error message"
    }
  ]
}

When passing in JSON, ensure that it is in quotes. An easy way to do this in Universe is QUOTE(JSON).

FIELD.NAME is the name of the field in the field property of the error object you are searching for.

ERROR.VALUE is the error message that corresponds to the FIELD.NAME that you are searching for. This does not have to be the full error message but can just be a substring.

For example, given you pass this JSON:

{
    "errors": [
      {
        "field": "customerName",
        "value": "Must be at least 3 characters"
      },
      {
        "field": "phone",
        "value": "Invalid phone syntax"
      }
    ]
}

You could then make the following assertion:

ASSERT.MISSING.JSON.ERRORS(JSON, "customerName", "Max 100 characters")

# ASSERT.HAS.JSON.SIMPLE.ERRORS

ASSERT.HAS.JSON.SIMPLE.ERRORS(JSON, SEARCH.VALUE)

This searches a JSON string that contains an error message.

This assumes your JSON will have this structure:

{
  "errors": ["error 1", "error 2"]
}

When passing in JSON, ensure that it is in quotes. An easy way to do this in Universe is QUOTE(JSON).

SEARCH.VALUE is the error message that you are searching for. This does not have to be the full error message but can just be a substring.

For example, given you pass this JSON:

{
    "errors": ["Must be at least 3 characters", "Invalid phone syntax"]
}

You could then make the following assertion:

ASSERT.HAS.JSON.SIMPLE.ERRORS(JSON, "Invalid phone")

# ASSERT.XML.HAS.NODE

ASSERT.XML.HAS.NODE(XML, XPATH, NAMESPACE, FOUND.VALUE)

This searches an XML string for a node specified in XPATH. If it finds the node, it will assign the value to FOUND.VALUE.

XPath is a syntax for defining parts of an XML document. Read more about it here: W3Schools (opens new window)

For example, given you pass this XML:

<response>
  <customer>
    <name>Gensler</name>
    <address>123 Some St.</address>
    <sales>1000000</sales>
  </customer>
</response>

You could then make the following assertion:

ASSERT.XML.HAS.NODE(XML, "response/customer/sales", "", FOUND.SALES)

In the example above, FOUND.SALES will be set to 1000000. So you could do further assertions like:

ASSERT.TRUE(FOUND.SALES GE 0)

# ASSERT.XML.HAS.VALUE

ASSERT.XML.HAS.VALUE(XML, XPATH, NAMESPACE, SEARCH.VALUE)

This searches an XML string for a node specified in XPATH and asserts that it has a specific value.

XPath is a syntax for defining parts of an XML document. Read more about it here: W3Schools (opens new window)

For example, given you pass this XML:

<response>
  <customer>
    <name>Gensler</name>
    <address>123 Some St.</address>
    <sales>1000000</sales>
  </customer>
</response>

You could then make the following assertion:

ASSERT.XML.HAS.VALUE(XML, "response/customer/name", "", "Gensler")

# ASSERT.XML.HAS.ATTRIBUTE.VALUE

ASSERT.XML.HAS.ATTRIBUTE(XML, XPATH, NAMESPACE, ATTRIBUTE.NAME, ATTRIBUTE.VALUE)

This searches an XML string for a node specified in XPATH and asserts that it has an attribute with a specific value.

XPath is a syntax for defining parts of an XML document. Read more about it here: W3Schools (opens new window)

For example, given you pass this XML:

<response>
  <customer priceclass="net">
    <name>Gensler</name>
    <address>123 Some St.</address>
    <sales>1000000</sales>
  </customer>
</response>

You could then make the following assertion:

ASSERT.XML.HAS.ATTRIBUTE.VALUE(XML, "response/customer", "", "priceclass", "net")

# ASSERT.XML.HAS.ATTRIBUTE

ASSERT.XML.HAS.ATTRIBUTE(XML, XPATH, NAMESPACE, ATTRIBUTE.NAME, FOUND.VALUE)

This searches an XML string for a node specified in XPATH and asserts that it has an attribute. If it finds the attribute, then it will set the attribute value to FOUND.VALUE. This could be useful if the attribute is an unkown value such as a calculation or a timestamp.

XPath is a syntax for defining parts of an XML document. Read more about it here: W3Schools (opens new window)

FOUND.VALUE is an OUT variable. It can be used to do further testing on the attribute's value if needed.

For example, given you pass this XML:

<response>
  <customer priceclass="net">
    <name>Gensler</name>
    <address>123 Some St.</address>
    <sales>1000000</sales>
  </customer>
</response>

You could then make the following assertion:

ASSERT.XML.HAS.ATTRIBUTE(XML, "response/customer", "", "priceclass", FOUND.PRICE.CLASS)

In the example above, FOUND.PRICE.CLASS will be set to net.

# ASSERT.XML.COUNT

ASSERT.XML.COUNT(XML.TEXT, XPATH, NAMESPACE, VALUE)

Assert that a list in XML has a certain amount of nodes.

XPath should identify the list element in the XML body. XPath is a syntax for defining parts of an XML document. Read more about it here: W3Schools (opens new window)

VALUE is the amount of nodes expected in the list.

For example, given you pass this XML:

<response>
  <customers>
    <customer>
      <name>Gensler</name>
    </customer>
    <customer>
      <name>Design, Inc.</name>
    </customer>
  </customers>
</response>

You could then make the following assertion:

ASSERT.XML.COUNT(XML, "response/customers", "", 2)