Writing Python Tests: Difference between revisions
Slowfranklin (talk | contribs) No edit summary |
mNo edit summary |
||
Line 2: | Line 2: | ||
Samba provides extensive [[Python]] bindings and test infrastructure, so if possible please write tests in Python as a first choice. Python provides exceptions and early returns, ensuring that subsequent code doesn't run after prerequisite checks have failed, many helper functions as well as setUp() and tearDown() routines allowing unit tests to be easily built. |
Samba provides extensive [[Python]] bindings and test infrastructure, so if possible please write tests in Python as a first choice. Python provides exceptions and early returns, ensuring that subsequent code doesn't run after prerequisite checks have failed, many helper functions as well as setUp() and tearDown() routines allowing unit tests to be easily built. |
||
==Protocol access== |
|||
If the protocol under test is [[DCERPC]], then [[PIDL]] will have already auto-generated [[Python]] bindings. |
|||
Likewise LDAP is easily accessed via [[LDB]]. |
|||
=Writing Python Tests for Samba= |
=Writing Python Tests for Samba= |
Revision as of 01:22, 23 May 2020
Use Python as the first choice
Samba provides extensive Python bindings and test infrastructure, so if possible please write tests in Python as a first choice. Python provides exceptions and early returns, ensuring that subsequent code doesn't run after prerequisite checks have failed, many helper functions as well as setUp() and tearDown() routines allowing unit tests to be easily built.
Protocol access
If the protocol under test is DCERPC, then PIDL will have already auto-generated Python bindings.
Likewise LDAP is easily accessed via LDB.
Writing Python Tests for Samba
unittest.TestCase
Python unittest.TestCase is the standard basis on which all of Samba's python based tests should be written.
This provides helpful routines such as assertTrue() etc, which provide a cosnsitent pattern in the tests.
samba.tests.TestCase
Samba's subclass samba.tests.TestCase, provides additional helper routines such as env_loadparm()
pydoc
You can explore the methods provided using pydoc:
PYTHONPATH=bin/python pydoc samba.tests.TestCase
Testing Samba binaries
When testing Samba binaries, please use:
samba.tests.BlackboxTestCase
Obtaining credentials for a sub process
A pattern like this is typical for passing credentials to a subprocess
creds = self.get_credentials() cmd_line_auth = "-U%s/%s%%%s" % (creds.get_domain(), creds.get_username(), creds.get_password())
Running the subprocess
Use self.check_run or self.check_output
self.check_run("ndrdump samr samr_CreateUser in %s" % (self.data_path("samr-CreateUser-in.dat")))
Testing samba-tool
samba-tool is a special case, as it is written in python. To avoid a fork()/exec() of python from python, use
samba.tests.samba_tool.base.SambaToolCmdTest
The runcmd() and runsubcmd() methods allows testing of a samba-tool command in the same process, which also allows the use of
samba.tests.TestCase.get_creds_ccache_name()
This example from source4/torture/drs/python/fsmo.py shows how to run an authenticated subcommand without forcing a new kinit:
ccache_name = self.get_creds_ccache_name() cmd_line_auth = "--krb5-ccache=%s" % ccache_name (result, out, err) = self.runsubcmd("fsmo", "transfer", "--role=%s" % role, "-H", "ldap://%s:389" % DC, cmd_line_auth)
Temporary directories
If you need a temp dir, use
samba.tests.TestCaseInTempDir
Both
samba.tests.samba_tool.base.SambaToolCmdTest
and
samba.tests.BlackboxTestCase
descend from this class, so the self.tempdir attribute is available with a temporary directory. The framework will assert that directory is empty when the test is done.
Good Patterns
Where to add new tests
Samba Tests are scattered around the code. However, in general, unless already related to or derived from other tests, new tests should be added in
samba/python/tests
use subunitrun
Tests should be run using subunitrun if possible, declared in tests.py via planpythontestsuite(), not planoldpythontestsuite()
Avoid innovation
Try not to make your new test special. The more our tests look like each other, the easier it is for new developers to follow the same patterns.
Mysterious error messages
AttributeError: 'module' object has no attribute 'foo'
A traceback that ends like this:
Traceback (most recent call last): [...] File "bin/python/samba/subunit/run.py", line 603, in createTests self.module) File "/usr/lib/python2.7/unittest/loader.py", line 130, in loadTestsFromNames suites = [self.loadTestsFromName(name, module) for name in names] File "/usr/lib/python2.7/unittest/loader.py", line 100, in loadTestsFromName parent, obj = obj, getattr(obj, part) AttributeError: 'module' object has no attribute 'foo'
usually means there was an exception raised when the test framework was importing your foo.py
test module. This means an error at the module's top level, or a syntax error in compilation, not an error in the actual tests (which are not run at this stage).
If the test runs fine for you locally but not in autobuild, the problem could be an ImportError
, caused by the use of a module that is not in the Python standard library. If the module is in Samba's thirdparty
directory, make sure you use this pattern:
import samba samba.ensure_third_party_module("dns", "dnspython") import dns.resolver
Debugging Python tests
Python tests that use subunit can be run directly by executing:
PYTHONPATH=bin/python python source4/scripting/bin/subunitrun TEST
Eg
PYTHONPATH=bin/python python source4/scripting/bin/subunitrun samba.tests.docs