pyATS Easypy enables the execution of multiple test scripts organized through a job file, with built-in logging and reporting features. It is commonly used in production environments where structured test execution and result archiving are required.
pyATS Easypy and Job FIle
Test scripts in pyATS can be executed in two ways: Standalone execution and Easypy execution.
So far, we have used the standalone method to run individual test scripts.
Easypy execution is designed for production environments, where structured logging, reporting, and archiving are essential. When scripts are run through the Easypy runtime, the environment takes full control of execution and offers several key benefits:
Run multiple test scripts together via a job file
Automatically generate task logs, result reports, and log archives
In this lesson, we won’t dive deeply into the full capabilities of job files. Instead, we will create a simple job file to execute multiple test scripts using the Easypy environment, and demonstrate its logging and reporting features.
pyATS Easypy Configuration Example
To demonstrate pyATS Easypy, I have prepared two AEtest test scripts:
The first script prints the IOS version of the devices to ensure they are all running the most current version.
The second script pings an external IP address (8.8.8.8) to verify that Internet connectivity is still functional.
The only difference between these scripts and the AEtest scripts we’ve previously discussed is that no testbed file is provided directly as input. Instead, the testbed is passed through pyATS Easypy at runtime.
(majid) majid@majid-ubuntu:~/devnet/pyats$ cat 8.1.easypy_testscript1.py from pyats import aetest from genie.testbed import load from pyats.async_ import pcall class Version_Check(aetest.Testcase): @aetest.setup def setup(self, testbed): self.testbed = load(testbed) self.device_list = [dev for dev in self.testbed.devices.values()] @aetest.test def check_version(self): def get_version(device): device.connect(log_stdout=False) output = device.parse('show version') print("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++") print("device=",device.name," version=",output['version']['version']) print("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++") device.disconnect() # Use pcall correctly by passing the devices as a positional argument pcall(get_version, device=self.device_list) if __name__ == '__main__': aetest.main()
(majid) majid@majid-ubuntu:~/devnet/pyats$ cat 8.2.easypy_testscript2.py import json from genie.testbed import load from pyats.async_ import pcall from pyats import aetest from genie.conf import Genie class PingCheck(aetest.Testcase): @aetest.setup def setup(self, testbed): self.testbed = load(testbed) self.device_list = [dev for dev in self.testbed.devices.values()] @aetest.test def check_ping(self): def ping_test(device): device.connect(log_stdout=False) output = device.execute("ping 8.8.8.8") print("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++") print("device=",device.name," ping output=",output) print("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++") device.disconnect() pcall(ping_test, device=self.device_list) if __name__ == '__main__': aetest.main()
What’s new here is the introduction of a simple job file, named 8.run_testcases_using_easypy.py, which is used to execute both test scripts.
(majid) majid@majid-ubuntu:~/devnet/pyats$ cat 8.run_testcases_using_easypy.py from pyats.easypy import run def main(): run('8.1.easypy_testscript1.py') run('8.2.easypy_testscript2.py')
While job files in pyATS are powerful and can include conditional logic, loops, and advanced orchestration, we will not explore those capabilities in this lesson. Our focus is simply on using a basic job file to run multiple scripts.
By running the command „pyats run job –help“, you can view the wide range of options and arguments supported by Easypy. These include:
Specifying testbed and job files
Configuring execution logic for test scripts
Setting up logging and reporting
Defining email notifications
And many other advanced parameters for customizing your test runs
(majid) majid@majid-ubuntu:~/devnet/pyats$ pyats run job --help from pyats.cli.__main__ import main Usage: pyats run job [file] [options] Example ------- pyats run job /path/to/jobfile.py pyats run job /path/to/jobfile.py --testbed-file /path/to/testbed.yaml Description: Runs a pyATS job file with the provided arguments, generating & report result. Configuration: -C, --configuration FILE easypy configuration yaml file for plugins Job Information: JOBFILE target jobfile to be launched --job-uid Unique ID identifiying this job run --pyats-configuration pyats configuration override file Suite Info: ... Tasks: --task-uids LOGIC Logic string to match task UIDs to run eg: "Or('Task-[12]')" Mailing: ... Reporting: ... Runinfo: ... Liveview: ... Testbed: -t, --testbed-file Specify testbed file location Clean: ... Bringup: ... Rerun: ... xUnit: ... HTML Logging: ... mapleClean: ... Abstract: ... pyATS Health: ... TopologyUpPlugin: ... WebEx: ... General Options: ...
We then execute the job file using the pyATS Easypy command:
pyats run job 8.run_testcases_using_easypy.py --testbed-file testbed.yaml ... 2025-05-28T11:51:53: %EASYPY-INFO: testscript = /home/majid/devnet/pyats/8.1.easypy_testscript1.py <module 'pyats.aetest.testscript.8.1.easypy_testscript1' from '/home/majid/devnet/pyats/8.1.easypy_testscript1.py'> ... 2025-05-28T11:51:53: %LOG-INFO: >>>> Begin child log /home/majid/.pyats/runinfo/8.run_testcases_using_easypy.2025May28_11:51:48.768120/TaskLog.Task-1:pid-908117 2025-05-28T11:51:53: %LOG-INFO: >>>> Begin child log /home/majid/.pyats/runinfo/8.run_testcases_using_easypy.2025May28_11:51:48.768120/TaskLog.Task-1:pid-908132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ device= R1 version= 17.1.1 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ device= R2 version= 17.1.1 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ... 2025-05-28T11:52:07: %EASYPY-INFO: testscript = /home/majid/devnet/pyats/8.2.easypy_testscript2.py <module 'pyats.aetest.testscript.8.2.easypy_testscript2' from '/home/majid/devnet/pyats/8.2.easypy_testscript2.py'> ... 2025-05-28T11:52:08: %LOG-INFO: >>>> Begin child log /home/majid/.pyats/runinfo/8.run_testcases_using_easypy.2025May28_11:51:48.768120/TaskLog.Task-2:pid-908302 2025-05-28T11:52:08: %LOG-INFO: >>>> Begin child log /home/majid/.pyats/runinfo/8.run_testcases_using_easypy.2025May28_11:51:48.768120/TaskLog.Task-2:pid-908316 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ device= R1 ping output= Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 8.8.8.8, timeout is 2 seconds: !!!!! Success rate is 100 percent (5/5), round-trip min/avg/max = 7/7/8 ms ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ device= R2 ping output= Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 8.8.8.8, timeout is 2 seconds: !!!!! Success rate is 100 percent (5/5), round-trip min/avg/max = 1/1/1 ms ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ... 2025-05-28T11:52:22: %EASYPY-INFO: +------------------------------------------------------------------------------+ 2025-05-28T11:52:22: %EASYPY-INFO: | Easypy Report | 2025-05-28T11:52:22: %EASYPY-INFO: +------------------------------------------------------------------------------+ 2025-05-28T11:52:22: %EASYPY-INFO: pyATS Instance : /home/majid 2025-05-28T11:52:22: %EASYPY-INFO: Python Version : cpython-3.12.3 (64bit) 2025-05-28T11:52:22: %EASYPY-INFO: CLI Arguments : /home/majid/bin/pyats run job 8.run_testcases_using_easypy.py --testbed-file testbed.yaml 2025-05-28T11:52:22: %EASYPY-INFO: User : majid 2025-05-28T11:52:22: %EASYPY-INFO: Host Server : majid-ubuntu 2025-05-28T11:52:22: %EASYPY-INFO: Host OS Version : Ubuntu 24.04 noble (x86_64) 2025-05-28T11:52:22: %EASYPY-INFO: 2025-05-28T11:52:22: %EASYPY-INFO: Job Information 2025-05-28T11:52:22: %EASYPY-INFO: Name : 8.run_testcases_using_easypy 2025-05-28T11:52:22: %EASYPY-INFO: Start time : 2025-05-28 11:51:53.470119+02:00 2025-05-28T11:52:22: %EASYPY-INFO: Stop time : 2025-05-28 11:52:21.679563+02:00 2025-05-28T11:52:22: %EASYPY-INFO: Elapsed time : 0:00:29 2025-05-28T11:52:22: %EASYPY-INFO: Archive : /home/majid/.pyats/archive/25-05/8.run_testcases_using_easypy.2025May28_11:51:48.768120.zip ... 2025-05-28T11:52:22: %EASYPY-INFO: Task-1: 8.1.easypy_testscript1 2025-05-28T11:52:22: %EASYPY-INFO: `-- Version_Check PASSED 2025-05-28T11:52:22: %EASYPY-INFO: |-- setup PASSED 2025-05-28T11:52:22: %EASYPY-INFO: `-- check_version PASSED 2025-05-28T11:52:22: %EASYPY-INFO: Task-2: 8.2.easypy_testscript2 2025-05-28T11:52:22: %EASYPY-INFO: `-- PingCheck PASSED 2025-05-28T11:52:22: %EASYPY-INFO: |-- setup PASSED 2025-05-28T11:52:22: %EASYPY-INFO: `-- check_ping PASSED 2025-05-28T11:52:22: %EASYPY-INFO: Sending report email... ... Pro Tip ------- Try the following command to view your logs: pyats logs view
In this example, the only argument passed to Easypy is the testbed file, demonstrating how testbed configuration can be provided at the Easypy runtime level instead of inside individual scripts.
Easypy begins by loading and running each test script defined in the job file. In this case, two AEtest scripts were executed: one that checks IOS versions of the devices to verify they are up to date, and another that performs connectivity checks by pinging a public IP (8.8.8.8). For each device, the test output is displayed, including version details and ping results with success rates.
At the end of execution, Easypy generates a structured summary report showing the results of each test section and script. Both scripts completed successfully with all test sections marked as PASSED. Additional metadata, such as job start/stop time, elapsed duration, archive location, and environment details, are also logged. Easypy also creates individual task logs and a zipped archive of all outputs, ready for review or automated distribution (e.g., email reports).
Monitor pyATS Logs and Reports
To monitor the logging and reporting results of a „pyats run
job
“
execution, we use the „pyats
logs view
“
command. This command launches a graphical web interface that provides a structured overview of the logs and reports generated during the pyATS job run.
Once executed, it hosts a local webpage displaying a summary of test results, including pass/fail status, a detailed results table, logs, and the commands executed during the test. The interface enables users to navigate through archived logs, examine individual test outcomes, and analyze execution details in a clear and organized format.
The screenshots below confirm that the test run was successful, with all tasks passing. The logs include execution metadata such as timestamps, testbed configurations, and command outputs. Additionally, the interface offers access to downloadable artifacts like reports, environment configurations, and test logs for further analysis.




