提交 5a147faf 编写于 作者: C Cleber Rosa

selftests/unit/test_remote.py: port from flexmock to mock (unittest.mock)

This is a port to the mock library that is in the standard in Python 3, and
it's available in Python 2, and already a requirement for Avocado.

The approach used on this port is to avoid excessive mocking, and use
the real code, unless when insteracting with dynamic and non-existing
components (such as a remote system).

A partial list of the changes when compared to the previous version:

* Args was made into a real argparse.Namespace instance because
  there's no need for it to be a mocked object.  Actually, it is
  better to have an exact object instance, rather than a mock when
  it's possible to.

* The "references" attribute being set on the, then mocked, job instance
  has been dropped, because the natural way of passing that to the job
  is using the "reference" key in args.  Also, while purely cosmetic,
  the references that look like the example instrumented tests have
  been renamed (passtest -> passtest.py).

* The "unique_id" attribute being set on the, then mocked, job instance
  had a value (1-sleeptest;0) completely incompatible with job IDs, and
  was removed from being set manually.

* This version does *not* mock "low level" remote execution of commands,
  such as running "env" or "avocado -v" on the remote host.  Instead, it
  mocks the end result of check_remote_avocado completely.

* The extra test on RemoteTestRunner.setup() seems unnecessary, because
  that is part of the run_suite() workflow.

* Checking if `__init__` was called is not be possible with mock. See
  https://docs.python.org/3/library/unittest.mock.html#mocking-magic-methodsSigned-off-by: NCleber Rosa <crosa@redhat.com>
上级 c4029004
import logging
import os
import argparse
import shutil
import unittest
from flexmock import flexmock, flexmock_teardown
try:
from unittest import mock
except ImportError:
import mock
from avocado.utils import archive
from avocado.core.job import Job
from avocado.core import version
from avocado.utils import process
import avocado_runner_remote
......@@ -25,154 +30,79 @@ class RemoteTestRunnerTest(unittest.TestCase):
""" Tests RemoteTestRunner """
def setUp(self):
Args = flexmock(test_result_total=1,
remote_username='username',
remote_hostname='hostname',
remote_port=22,
remote_password='password',
remote_key_file=None,
remote_timeout=60,
show_job_log=False,
mux_yaml=['~/avocado/tests/foo.yaml',
'~/avocado/tests/bar/baz.yaml'],
dry_run=True,
env_keep=None)
log = flexmock()
log.should_receive("info")
result_dispatcher = flexmock()
result_dispatcher.should_receive("map_method")
job = flexmock(args=Args, log=log,
references=['/tests/sleeptest', '/tests/other/test',
'passtest'], unique_id='1-sleeptest;0',
logdir="/local/path",
_result_events_dispatcher=result_dispatcher)
flexmock(avocado_runner_remote.RemoteTestRunner).should_receive('__init__')
self.runner = avocado_runner_remote.RemoteTestRunner(job, None)
self.runner.job = job
filehandler = logging.StreamHandler()
flexmock(logging).should_receive("FileHandler").and_return(filehandler)
test_results = flexmock(stdout=JSON_RESULTS, exit_status=0)
stream = flexmock(job_unique_id='1-sleeptest;0',
debuglog='/local/path/dirname')
Remote = flexmock()
Remoter = flexmock(avocado_runner_remote.Remote)
Remoter.new_instances(Remote)
args_version = 'avocado -v'
version_result = flexmock(stderr='Avocado 1.2', exit_status=0)
args_env = 'env'
env_result = flexmock(stdout='''XDG_SESSION_ID=20
HOSTNAME=rhel7.0
SELINUX_ROLE_REQUESTED=
SHELL=/bin/bash
TERM=vt100
HISTSIZE=1000
SSH_CLIENT=192.168.124.1 52948 22
SELINUX_USE_CURRENT_RANGE=
SSH_TTY=/dev/pts/0
USER=root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
MAIL=/var/spool/mail/root
PWD=/root
LANG=en_US.UTF-8
SELINUX_LEVEL_REQUESTED=
HISTCONTROL=ignoredups
HOME=/root
SHLVL=2
LOGNAME=root
SSH_CONNECTION=192.168.124.1 52948 192.168.124.65 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/0
_=/usr/bin/env''', exit_status=0)
(Remote.should_receive('run')
.with_args(args_env, ignore_status=True, timeout=60)
.once().and_return(env_result))
(Remote.should_receive('run')
.with_args(args_version, ignore_status=True, timeout=60)
.once().and_return(version_result))
args = ("avocado run --force-job-id 1-sleeptest;0 "
"--json - --archive /tests/sleeptest /tests/other/test "
"passtest -m ~/avocado/tests/foo.yaml "
"~/avocado/tests/bar/baz.yaml --dry-run")
(Remote.should_receive('run')
.with_args(args, timeout=61, ignore_status=True)
.once().and_return(test_results))
Result = flexmock(remote=Remote, references=['sleeptest'],
stream=stream, timeout=None,
args=flexmock(show_job_log=False,
mux_yaml=['foo.yaml', 'bar/baz.yaml'],
dry_run=True))
args = {'name': '1-sleeptest;0', 'time_end': 1.23,
'status': u'PASS', 'time_start': 0,
'time_elapsed': 1.23, 'job_unique_id': '',
'fail_reason': u'None',
'logdir': u'/local/path/test-results/1-sleeptest;0',
'logfile': u'/local/path/test-results/1-sleeptest;0/debug.log',
'job_logdir': u'/local/path'}
Result.should_receive('start_test').once().with_args(args).ordered()
Result.should_receive('check_test').once().with_args(args).ordered()
(Remote.should_receive('receive_files')
.with_args('/local/path', '/home/user/avocado/logs/run-2014-05-26-'
'15.45.37.zip')).once().ordered()
(flexmock(archive).should_receive('uncompress')
.with_args('/local/path/run-2014-05-26-15.45.37.zip', '/local/path')
.once().ordered())
(flexmock(os).should_receive('remove')
.with_args('/local/path/run-2014-05-26-15.45.37.zip').once()
.ordered())
Result.should_receive('end_tests').once().ordered()
self.runner.result = Result
def tearDown(self):
flexmock_teardown()
def test_run_suite(self):
""" Test RemoteTestRunner.run_suite() """
self.runner.run_suite(None, None, 61)
flexmock_teardown() # Checks the expectations
class RemoteTestRunnerSetup(unittest.TestCase):
""" Tests the RemoteTestRunner setup() method"""
def setUp(self):
Remote = flexmock()
remote_remote = flexmock(avocado_runner_remote)
(remote_remote.should_receive('Remote')
.with_args(hostname='hostname', username='username',
password='password', key_filename=None, port=22,
timeout=60, env_keep=None)
.once().ordered()
.and_return(Remote))
Args = flexmock(test_result_total=1,
reference=['/tests/sleeptest', '/tests/other/test',
'passtest'],
remote_username='username',
remote_hostname='hostname',
remote_port=22,
remote_password='password',
remote_key_file=None,
remote_timeout=60,
show_job_log=False,
env_keep=None)
log = flexmock()
log.should_receive("info")
job = flexmock(args=Args, log=log)
self.runner = avocado_runner_remote.RemoteTestRunner(job, None)
def tearDown(self):
flexmock_teardown()
def test_setup(self):
""" Tests RemoteResult.test_setup() """
self.runner.setup()
flexmock_teardown()
"""
Test RemoteTestRunner.run_suite()
The general idea of this test is to:
1) Create the machinery necessary to get a RemoteTestRunner
setup inside a job, or looking at it the other way around, to
have a runner that is created with a valid job.
2) Mock the interactions with a remote host. This is done here
basically by mocking 'Remote' and 'fabric' usage.
3) Provide a polluted JSON to be parsed by the RemoteTestRunner
4) Assert that those results are properly parsed into the
job's result
"""
job_args = argparse.Namespace(test_result_total=1,
remote_username='username',
remote_hostname='hostname',
remote_port=22,
remote_password='password',
remote_key_file=None,
remote_timeout=60,
show_job_log=False,
mux_yaml=['~/avocado/tests/foo.yaml',
'~/avocado/tests/bar/baz.yaml'],
dry_run=True,
env_keep=None,
reference=['/tests/sleeptest.py',
'/tests/other/test',
'passtest.py'])
try:
job = Job(job_args)
runner = avocado_runner_remote.RemoteTestRunner(job, job.result)
return_value = (True, (version.MAJOR, version.MINOR))
runner.check_remote_avocado = mock.Mock(return_value=return_value)
# These are mocked at their source, and will prevent fabric from
# trying to contact remote hosts
with mock.patch('avocado_runner_remote.Remote'):
runner.remote = avocado_runner_remote.Remote(job_args.remote_hostname)
# This is the result that the run_suite() will get from remote.run
remote_run_result = process.CmdResult()
remote_run_result.stdout = JSON_RESULTS
remote_run_result.exit_status = 0
runner.remote.run = mock.Mock(return_value=remote_run_result)
# We have to fake the uncompressing and removal of the zip
# archive that was never generated on the "remote" end
# This test could be expand by mocking creating an actual
# zip file instead, but it's really overkill
with mock.patch('avocado_runner_remote.archive.uncompress'):
with mock.patch('avocado_runner_remote.os.remove'):
runner.run_suite(None, None, 61)
# The job was created with dry_run so it should have a zeroed id
self.assertEqual(job.result.job_unique_id, '0' * 40)
self.assertEqual(job.result.tests_run, 1)
self.assertEqual(job.result.passed, 1)
cmd_line = ('avocado run --force-job-id '
'0000000000000000000000000000000000000000 --json - '
'--archive /tests/sleeptest.py /tests/other/test '
'passtest.py -m ~/avocado/tests/foo.yaml '
'~/avocado/tests/bar/baz.yaml --dry-run')
runner.remote.run.assert_called_with(cmd_line,
ignore_status=True,
timeout=61)
finally:
shutil.rmtree(job.args.base_logdir)
if __name__ == '__main__':
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册