python-3.xpytestpytest-fixtures

How to call ssh connect fixture in teardown


I want to test some scenarios by executing command through ssh connection. I need the ssh connection fixture to be called second time.

So my scenario is like:

Inside conftest.py file

@pytest.fixture(scope="session")

def get_ssh_connection(vars, logger):

    ssh = SshClient(ip=vars["ip"],
                    port=vars["port"],
                    user=vars["username"],
                    passwd=vars["pw"])
    ssh.connect()
    yield ssh
    ssh.close()

Inside test script:

@pytest.fixture(scope="class", autouse=True)
def setup_teardown(self, list):
    self.ssh.exec_cmd(f"mv {file} {newfile}")  # rename file
    self.restartDevice()  #ssh connection closed
    yield
    **self.ssh.exec_cmd**(f"mv {newfile} {file}") #restore file
    self.restartDevice()

How to enable this ssh connection (highlighted one) after restartdevice since ssh connection is a fixture as session?


Solution

  • Here is an example which demonstrates this scenario:

    1. Before the tests start, a fixture (ssh_client) will connect to a remote host via ssh.
    2. The fixture then perform some prep works, then reboot
    3. The fixture then keep trying to connect to the remote host until success (meaning the remote host has successfully come online)
    4. At this point, the control will pass to the tests, which can use the ssh_client fixture. I am writing 2 simple tests in this case.
    5. At the end of the session, the fixture will perform some clean up.

    Code

    # conftest.py
    import logging
    import time
    
    import paramiko
    import pytest
    
    
    @pytest.fixture(scope="session")
    def ssh_client():
        """
        Create a ssh client and perform some prep works remotely.
        """
        logging.info("First connection...")
        client = paramiko.SSHClient()
        client.load_system_host_keys()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
        client.connect("192.168.64.18", username="ubuntu")
        logging.info("Connected")
    
        logging.info("Prep the remote host")
        # Perform prep works here
    
        logging.info("Reboot the remote host")
        client.exec_command("sudo shutdown -r now")
    
        logging.info("Second connection...")
        while True:
            try:
                client.connect("192.168.64.18", username="ubuntu")
                logging.info("Connected again")
                break
            except (
                paramiko.SSHException,
                paramiko.ssh_exception.NoValidConnectionsError,
            ):
                time.sleep(3)
    
        yield client
    
        logging.info("Clean up remote host")
        # Do something here to clean up
    
    # test_it.py
    import paramiko
    
    
    def test_user_is_not_root(ssh_client: paramiko.SSHClient):
        _, stdout, _ = ssh_client.exec_command("whoami")
        user = stdout.read().decode().strip()
        assert user != "root"
    
    
    def test_os_release_exists(ssh_client: paramiko.SSHClient):
        with ssh_client.open_sftp() as sftp:
            sftp.stat("/etc/os-release")  # Will raise if not exist
    
    # pyproject.toml
    [tool.pytest.ini_options]
    addopts = "--strict-markers"
    log_cli_level = "INFO"
    log_cli = true
    

    Notes