Examples

This section contains a few simple examples aimed towards guiding users on writing their first aetest based testscripts.

Note

more elaborate examples can be found in GitHub example repository.

Hello World

This is a very simply testscript demonstrating the hello world usage of aetest. It contains a single Testcase with a single test. Keep in mind that this is the smallest possible testscript, as CommonSetup and CommonCleanup are optional sections block.

# Example
# -------
#
#   hello world

import logging
from pyats import aetest

logger = logging.getLogger(__name__)

class HelloWorld(aetest.Testcase):

    @aetest.test
    def test(self):
        logger.info('Hello World!')

# main()
if __name__ == '__main__':
    # set logger level
    logger.setLevel(logging.INFO)

    aetest.main()

Tip

do not submit to regression: insignificant test coverage

You can save this content to file named hello_world.py, and try to run it using Standalone Execution method.

bash$ python hello_world.py

Script Arguments

This example focuses on how to use Script Arguments and pass them to your testscript into parameters, using both Standalone Execution and Easypy Execution.

# Example
# -------
#
#   script arguments demo

import logging
from pyats import aetest

logger = logging.getLogger(__name__)

class Testcase(aetest.Testcase):

    @aetest.test
    def test(self, testbed, vlan):
        logger.info('Testbed = %s' % testbed)
        logger.info('Vlan =  %s' % vlan)

# main()
if __name__ == '__main__':

    # set logger level
    logger.setLevel(logging.INFO)

    # local imports
    import sys
    import argparse
    from pyats.topology import loader

    parser = argparse.ArgumentParser(description = "standalone parser")
    parser.add_argument('--testbed', dest = 'testbed')
    parser.add_argument('--vlan', dest = 'vlan')

    # parse args
    args, sys.argv[1:] = parser.parse_known_args(sys.argv[1:])

    # post-parsing processing
    testbed = loader.load(args.testbed)
    vlan = int(args.vlan)

    # and pass all arguments to aetest.main() as kwargs
    aetest.main(testbed = testbed, vlan = vlan)

Assuming the above testscript is saved into script_argument_demo.py, then when running under standalone execution, make sure to pass in both --testbed and --vlan arguments:

bash$ python script_argument_demo.py --testbed /path/to/my/testbed.yaml --vlan 50

To run under Easypy, a job file needs to be created for it:

# Example
# -------
#
#   job file demonstrating passing script arguments to testscripts

from pyats.easypy import run

# job file requires a main block
def main():

    run('script_argument_demo.py', vlan = 50)

Keep in mind that during Easypy Execution, the testbed argument is automatically passed to the testscript if pyats run job was run with the --testbed-file and/or --logical-testbed-file arguments. Thus, save this to script_argument_demo_job.py file and run it with:

bash$ pyats run job script_argument_demo_job.py --testbed-file /path/to/my/testbed.yaml

Feature Usage

Although loops and Flow Control features can be used (hard-coded) directly in your main testscript, a good practice to follow is to always:

  • develop a library of testcases, then

  • build and control your testscripts by reference and inheritance.

This allows multiple scripts to share the same basic test code, but be driven by varying parameters & etc. This also allows users to write testcases, but apply loops to them as they see fit (in the inherited testcase).

# Example
# -------
#
#   the base testcase library script (to be inherited by other scripts)
#   let's call this script: base_script.py

from pyats import aetest

class MathTest(aetest.Testcase):

    def test_plus(self):
        '''test requires the definition of a & b at testcase level'''

        assert self.a + self.b < 1000

Note that in the above script, we defined a testcase, but its required values (a/b) is not defined - the testcase expects to be inherited from.

# Example
# -------
#
#   the script that inherits from the base_script and gives it meaning

from base_script import MathTest

class RealMathTest(MathTest):

    # provide uid and grouping information
    uid = 'rocket_science_math_test'
    groups = ('elementary', 'basic')

    # give values for the tests
    a = 1
    b = 2

When this testscript is run, it is given a meaningful uid, two unique testcase groups, and is driven by new data values, all while the content of the testcase’s test remaining the same.

This concept allows testcases to be classified & driven differently dependent on the actual script usage, and avoids hard-coding data, values and testcase classifications within a testscript, further avoiding the need to constantly modify and/or duplicate testscripts.

Note

more elaborate examples can be found in GitHub example repository.

Mega Looping

The following example is a mega loop script: it demonstrates every possible way of Looping Sections definitions.

# Example
# -------
#
#   loop everything!

import logging
from pyats import aetest

logger = logging.getLogger(__name__)

# static variable
VLANS = list(range(1, 4096))

class CommonSetup(aetest.CommonSetup):

    @aetest.subsection
    def check_testbed(self, testbed):
        '''
        checking testbed information
        '''

        logger.info('Testbed = %s' % testbed)
        # do some testbed checking
        # ...

    @aetest.subsection.loop(vlan=VLANS)
    def configure_vlan(self, vlan):
        '''
        configure every vlan, each being a subsection
        '''

        logger.info("configuring vlan: %s" % vlan)
        # do the configuration
        # ...

    # dynamically assign looping of Testcase
    # based on script argument information
    @aetest.subsection
    def mark_testcase_for_looping(self, interfaces):
        '''
        marking testcase for looping based on script argument interfaces
        '''

        aetest.loop.mark(InterfaceFlapping, interface = interfaces)


class InterfaceFlapping(aetest.Testcase):
    '''
    tests interface flapping, requires parameter 'interface'
    '''

    @aetest.setup
    def setup(self, interface):
        logger.info('testing interface: %s' % interface)

    @aetest.test.loop(status=['up', 'down'])
    def test_status(self, status):
        '''
        check that intf status can be flapped
        '''
        logger.info('configure interface status to: %s' % status)
        # do testing
        # ...

@aetest.loop(vlan = VLANS)
class Traffic(aetest.Testcase):
    '''
    send traffic on all vlans on all interfaces
    '''

    @aetest.setup
    def setup(self, interfaces):
        '''
        mark traffic test with looping through interfaces
        '''
        aetest.loop.mark(self.test, interface = interfaces)

    def test(self, interface, vlan):
        '''
        send traffic to vlan + interface
        '''
        logger.info('interface: %s' % interface)
        logger.info('vlan: %s' % vlan)
        # send traffic
        # ...


class CommonCleanup(aetest.CommonCleanup):

    @aetest.subsection.loop(vlan=VLANS)
    def unconfigure_vlan(self, vlan):
        '''
        unconfigure every vlan, each being a subsection
        '''

        logger.info("configuring vlan: %s" % vlan)
        # do the configuration
        # ...

# main()
if __name__ == '__main__':

    # set logger level
    logger.setLevel(logging.INFO)

    # local imports
    import sys
    import argparse
    from pyats.topology import loader

    parser = argparse.ArgumentParser(description = "standalone parser")
    parser.add_argument('--testbed', dest = 'testbed')
    parser.add_argument('--interfaces', dest = 'interfaces')

    # parse args
    args, sys.argv[1:] = parser.parse_known_args(sys.argv[1:])

    # post-parsing processing
    testbed = loader.load(args.testbed)
    interfaces = args.interfaces.split(',')

    # and pass all arguments to aetest.main() as kwargs
    aetest.main(testbed = testbed, interfaces = interfaces)

Standalone Execution Command:

bash$ python mega_looping.py --testbed tb.yaml --interfaces="Ethernet1/1,Ethernet1/2"

To run under Easypy, create the following job file:

# Example
# -------
#
#   mega looping jobfile

from pyats.easypy import run

def main():

    run('mega_looping.py', interfaces=['Ethernet1/1', 'Ethernet1/2'])

And run pyats run job:

bash$ pyats run job mega_looping_job.py --testbed-file tb.yaml