Messagerobot

Automatically Validate a Library of Messages

Automatically Validate
a Library of Messages

Posted on: January 8, 2021


Most LIXI2 integrations can benefit from fully automating the validation of a library of LIXI2 messages against the LIXI schemas for testing purposes.

You may have a series of processes that generate LIXI2 messages for submitting to an API or you may host an API that consumes LIXI2 messages. In both situations, the capability to automatically validate a set of messages is likely needed.

In an earlier post, I showed how you can automatically access our standards in LIXILab for the purpose of triggering your own process (Automatically Trigger a Build Process with our Standards Releases).

This blog post builds on this to fetch the latest standards, fetch a library of test messages (we use the LIXI Sample Repository, but you would likely replace this with your own test message library), and validate all the test messages against the latest standards.

Step 1. Create Folder and Clone Projects

Before starting, you need to have Python 3, have already installed the LIXI Python Package and have access to LIXILab.

Start this process by creating a folder called 'lixi-validation-demo' - I've created this under the 'C:\temp\' directory.

Then in a command or bash window and use the git clone command to clone both the LIXI2 schemas and the LIXI2 samples projects locally from LIXILab. If this is your first time running this command, you will be asked for your credentials for LIXILab.

C:\temp\lixi-validation-demo>git clone https://standards.lixi.org.au/lixi2/schemas.git
Cloning into 'schemas'...
remote: Enumerating objects: 319, done.
remote: Counting objects: 100% (319/319), done.
remote: Compressing objects: 100% (142/142), done.
Receiving objects: 100% (2850/2850), 10.47 MiB | 1.13 MiB/sving objects:  99% (2849/2850), 10.47 MiB | 1.13 MiB/s
Receiving objects: 100% (2850/2850), 10.73 MiB | 1.19 MiB/s, done.
Resolving deltas: 100% (2667/2667), done.
Updating files: 100% (802/802), done.

C:\temp\lixi-validation-demo>

C:\temp\lixi-validation-demo>git clone https://standards.lixi.org.au/lixi2/samples.git
Cloning into 'samples'...
remote: Enumerating objects: 2748, done.
remote: Counting objects: 100% (2748/2748), done.
remote: Compressing objects: 100% (689/689), done.
remote: Total 2748 (delta 2089), reused 2705 (delta 2052)
Receiving objects: 100% (2748/2748), 1.15 MiB | 1.30 MiB/s, done.
Resolving deltas: 100% (2089/2089), done.

C:\temp\lixi-validation-demo>

Step 2. Copy the Python Code into a New File

In the new folder create an empty file called validate_all_standalone_script.py and copy the code from the block at the bottom of this page into the file and save it.

After completing this, you will have two sub-directories and a single python script.

└── lixi-validation-demo
    ├── samples
    ├── schemas
    └── validate_all_standalone_script.py

Step 3. Run the Python Script

The heart of this process revolves around the 'lixi.read_message method' in the LIXI2 Python Library. After executing read_message, you are able to interrogate the read_message response to determine and display the type of error, and choose and appropriate action - in our case we'll print the details.

Depending on your Python installation, you can now run the script that you created and populated in step 2. You could use an IDE such as Visual Studio Code or execute the script from a command or bash session. For example, you can run it at the Windows CMD prompt as follows.

C:\temp\lixi-validation-demo>python validate_all_standalone_script.py
Validating 214 files.
Succesfully Validated 214 files.
Failed to Validate 0
done

C:\temp\lixi-validation-demo>

Step 4. What Next? Over to you ...

This is just a demonstration of how you might start to plug together various components of LIXI2 on your journey to automate your software delivery lifecycle.

For example, you might use a variation of this process to roll forward all of your samples from your current version to the latest release and retest all your samples to find out anything that might have broken as a result of the upgrade.

Python Code to Save in 'validate_all_standalone_script.py'

import glob, os, lixi

# Retrieve this scripts path
this_path = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))

# Derive the path to the cloned schemas
schema_path = os.path.join(this_path, 'schemas','xsd')

# Derive the path to the cloned samples
glob_search_string = os.path.join(this_path, 'samples','Samples') +'/**/*.xml'

# Set the schema folder path in the lixi library
lixi.set_schema_folder(schema_path)

# Ininitalise a list of valid files
valid_file_list = []

# Ininitalise a dictionary of invalid files to store the error
invalid_file_dict = {}

# Create a list of files to validate
files_to_check = glob.glob(glob_search_string , recursive=True)

# Print the number of files that are found to be validated
print('Validating ' + str(len(files_to_check)) + ' files.')

# Loop through the files
for filepath in files_to_check:
    try:
        # Validate each message with the LIXI Library
        xml_obj = lixi.read_message(message_path=filepath)

        # If successful, add the file path to the list of valid files
        valid_file_list.append(filepath)

    except Exception as e:

        # If validation failes, add the file path to the dictionary of invalid files with the error
        if str(e.__class__.__name__) == 'LIXIValidationError':
           invalid_file_dict[filepath] = e.error_log
        elif  str(e.__class__.__name__) == 'LIXIInvalidSyntax':
           invalid_file_dict[filepath] = e
        elif  str(e.__class__.__name__) == 'LIXIResouceNotFoundError':
            invalid_file_dict[filepath] = e

print('Succesfully Validated ' + str(len(valid_file_list)) + ' files.')
print('Failed to Validate ' + str(len(invalid_file_dict)))

# Loop through the dictionary of invalid file and print the details
for invalid_file, invalid_file_error_log in invalid_file_dict.items():
    print ('Filename : ' + invalid_file)
    if type(invalid_file_error_log).__name__ in('LIXIInvalidSyntax', 'LIXIResouceNotFoundError'):
        print('Error: ' + invalid_file_error_log.args[0].strip())
    else:
        for error_item in invalid_file_error_log: 
            print(error_item.message_location.strip())
            print(error_item.message.strip())
            
print('done')

Related Blogs


Written by:
Shane Rigby, LIXI Limited CEO
First Published: January 8, 2021