Pytest

Pytest is a utility to unit test python code. We use pytest and not __main__ to test all functionality so they can be automatically run and reports can be generated. A project that does not have a sufficient number of tests to make sure the module works can not be accepted.

Installation

The pytest module can be installed with the help of pip utility:

$ pip install pytest

This will install the pytest module in the current Python distribution. All tests are included in the folder tests. For example for the cloudmesh-cloud module they are in

If the order of the tests is important make sure the tests are specified in alphabetical order while introducing a numbering such as

+cm
  + cloudmesh
  + tests
    - test_01_topic1.py
    - test_02_topic2.py
    - test_03_topic2.py

Cloudmesh Debugging Information

To switch on debugging information for the tests you can do this with

cms set trace=True
cms set debug=True
cms set verbose=10

After you are done testing, you may want to set them back to

cms set trace=True
cms set debug=True
cms set verbose=10

You can also set them within a test with the command

from cloudmesh.common3.Benchmark import Benchmark

Benchmark.debug()

Test Specification and Execution

A simple example for a test is

Note that all test python programs have specific function names of the form

def test_topic (self)

Through the class decorator, they are executed in order

A test may also have a method def setup(self) which is run prior to each

other method.

A test method includes one or multiple asserts that check if a particular test succeeds and reports this to pytest to expose the information if a test succeeds or fails, when running it

To have better visual separation of tests with the –capture=no option, all pytest functions in cloudmesh start with a HEADING(), which will print a banner with the function name. Invocation is simply done with the comment lines you see on top that you will include. In our case the test is called test_key.py so we include on the top:

###############################################################
# pytest -v --capture=no tests/test_key.py
# pytest -v  tests/test_key.py
# pytest -v --capture=no -v tests/test_key.py:Test_key.<METHODNAME>
###############################################################

Make sure that you place this comment in your tests. to remind the developers how to execute your test from the main directory. If you need special instructions, please add them here.

The following example is our simple pytest for key. The file is stored at tests/test_key.py

First, we import the needed classes and methods we like to test. We define a class, and then we define the methods. such as the setup and the actual tests.

You run it with

$ pytest -v --capture=no tests/test_key.py
###############################################################
# pytest -v --capture=no tests/test_key.py
# pytest -v  tests/test_key.py
# pytest -v --capture=no -v --nocapture tests/test_key.py:Test_key.<METHIDNAME>
###############################################################
from pprint import pprint
from cloudmesh.common.Printer import Printer
from cloudmesh.common.util import HEADING, banner
from cloudmesh.management.configuration.SSHkey import SSHkey
from cloudmesh.management.configuration.config import Config
from cloudmesh.common.StopWatch import StopWatch

@pytest.mark.incremental
class TestKey:

    def setup(self):
        self.sshkey = SSHkey()


    def test_find_key(self):
        HEADING()
        StopWatch.stop("key")
        pprint(self.sshkey)
        print(self.sshkey)
        print(type(self.sshkey))
        pprint(self.sshkey.__dict__)

        assert self.sshkey.__dict__  is not None


    def test__key_from_git(self):
        HEADING()
        config = Config()
        username = config["cloudmesh.profile.github"]
        print ("Username:", username)
        StopWatch.start("get from git")
        keys = self.sshkey.get_from_git(username)
        StopWatch.stop("get from git")
        pprint (keys)
        print(Printer.flatwrite(keys,
                            sort_keys=("name"),
                            order=["name", "fingerprint"],
                            header=["Name", "Fingerprint"])
              )

        assert len(keys) > 0


    def test_results(self):
        HEADING()
        banner(f"Benchmark results for Keys")
        StopWatch.benchmark()

The output with pytest tests/test_key.py does not provide any detail, but just reports if tests fail or succeed.

----------------------------------------------------------------------
Ran 2 tests in 0.457s

OK

The output with pytest -v tests/test_key.py results in

tests.test_key.TestName.test_01_key ... ok
tests.test_key.TestName.test_02_git ... ok

----------------------------------------------------------------------
Ran 2 tests in 1.072s

OK

During the development phase, you want to use

pytest -v --capture=no tests/test_key.py

which prints all print statements