Commits

holger krekel committed 61e9a35

last state

Comments (0)

Files changed (10)

+import subprocess
+
+def pytest_funcarg__cmd(request):
+    tmpdir = request.getfuncargvalue("tmpdir")
+    return Command(tmpdir)
+
+class Command:
+    def __init__(self, tmpdir):
+        self.tmpdir = tmpdir
+        self.stdout_file = tmpdir.join("stdout")
+        self.stderr_file = tmpdir.join("stderr")
+
+    def run(self, *args):
+        f_stdout = self.stdout_file.open('w')
+        f_stderr = self.stderr_file.open('w')
+        popen = subprocess.Popen(list(args), stdout=f_stdout, stderr=f_stderr)
+        f_stdout.close()
+        f_stderr.close()
+        popen.communicate()
+        retcode = popen.wait()
+        return Result(retcode, args, self)
+
+class Result:
+    def __init__(self, retcode, args, command):
+        self.retcode = retcode 
+        self.args = args
+        self.command = command
+        self.stdout = command.stdout_file.read()
+        self.stderr = command.stderr_file.read()
+
+
+def test_version(cmd):
+    result = cmd.run("py.test", "--version")
+    assert result.retcode == 0
+    x = result.stderr.strip()
+    assert "1.3.2" in x
 py.process.cmdexec("zip -r %s %s" % (zipname, tdir.basename))
 print "created", zipname
 
-#out = py.process.cmdexec("scp %s code:/www/codespeak.net/htdocs/py/dist/test/tutorial/" % zipname)
-#print out
+out = py.process.cmdexec("scp %s code:/www/codespeak.net/htdocs/py/dist/test/tutorial/" % zipname)
+print out
 

pytest-advanced.pdf

Binary file modified.

pytest-advanced.txt

 On to py.test parametrization 
 ===================================================
 
-py.test provides a unique parametrization mechanism:
+py.test provides a funcargs parametrization mechanism:
 
 - a test function can be invoked with different sets
   of arguments 
 on test functions and allows to generate multiple invocations using
 different parameter sets. 
 
+**simple interactive example**
+
 
 Example: re-running with multiple argument values
 =======================================================
 
 - run ``py.test --checkremote`` 
 
+Server Example: setups spanning a test session 
+====================================================
+
+The ``server`` example implements: 
+
+- a funcarg with a setup scope of a whole session
+- for managing expensive (slow) resources 
+- makes use of the ``cached_setup`` helper
+- setup is driven by funcarg factory only
+- scope can be influenced by command line option
+
+see directory ``server``. 
 
 py.test hooks and plugins 
 ===================================================
 - ``conftest.py`` files are considered as "local plugins" 
 - global plugins integrate via a setuptools-entry point
 - ``pytest_addoption(parser)`` is one such extension hook 
+- hooks are a **metaprogramming** facility with respect
+  to test code 
 
 local plugins: conftest.py 
 ===============================
 - can contain hook implementations 
 - can add command line options
 - can specify required plugins
-- best put into ``test/conftest.py`` 
+- can be put into ``test/conftest.py`` or root dir
+- can specify defaults for command line options
 
 a simple config: ignoring directories
 ==========================================
 this will prevent py.test from trying to collect
 the ``test_myfile.py`` test module or in the ``data`` 
 directory.  Paths are specified relative to 
-the directory which contains conftest.py 
+the directory which contains ``conftest.py``. 
 
 a simple default option: verbose 
 ==========================================
 ::
 
     # conftest.py
-    pytest_option_verbose = True   # always run in verbose mode
-    pytest_option_exitfirst = True # always exit on first fail
+    option_verbose = True  # always run in verbose mode
+    option_maxfail = 2     # stop after two failures 
 
 notes: 
 
 to the ``conftest.py`` as you like (see 
 ``py.test --help-config`` for names you can use).
 
+
+Other interesting hooks 
+==========================================
+
+let's look together at other available 
+hooks and example usages: 
+
+- ``pytest_configure``
+- ``pytest_terminal_summary``
+- ``pytest_runtest_setup``
+- ``pytest_runtest_call``
+- ``pytest_runtest_teardown``
+- ... 
+
+integrating doctests 
+====================
+
+- py.test runs ``test*.txt`` doctest files 
+- concise reporting on failures 
+- ``--doctests-glob=*.txt`` modifies discovery 
+- ``--doctest-modules`` enables searching in test modules
+- see ``py.test --help-config`` for ``conftest.py`` option names 
+- (demo if time permits) 
+
 break 
 ===================================================
 
 
 http://marikaz.deviantart.com/  CC 3.0 AN-ND
 
+differences to nose
+============================
+
+py.test (compared to ``nose``): 
+
+- allows to simply use ``assert`` expressions 
+- is Python3 compatible (since a year) 
+- has funcarg mechanism 
+- extended parametrization 
+- deep extensibility (reporting, non-py items)
+- skipping and **xfail** mechanism 
+- less powerful support for doctests (?) 
+- can only run basic nosetests and unittests
+
 Installing "global" plugins
 ===============================
 
 - we would like to rather work in virtualenvs
 
 
-
 tox, the virtualenv test automation tool
 ============================================
 
 - ``tox`` creates virtualenvs and runs commands in them
 - ``tox`` is driven from a simple ``tox.ini`` file
 - allows to test against multiple interpreters at once
+- helps to integrate test runs with **Hudson** 
 
 **Tox makes it easy to integrate py.test**
 
 
 For what kind of scenarios do you want to write tests? 
 
-Some possible further topics:
+Some possible further topics for this tutorial:
 
+* ``server``: fixtures that span a whole test session 
+* ``cmd``: testing command line tools 
 * generating JunitXML result files for use with Hudson 
-* fixtures that span a whole test session 
 * monkeypatching attributes/modules/environments 
-* integrating nose or unittests into a py.test run 
 * sending test results to a pastebin service 
+* integrating nose or unittests into a tox/py.test run 
 
 Let's do it together ... (interactive sessions) 
 

pytest-basic.pdf

Binary file modified.
 
 - test files are imported as normal python modules
 - make test directories a package to disambiguate
-
 **first non `__init__.py` dir is inserted into sys.path**
 
 no boilerplate python test code
     def test_function():
         ... # will only run on win32 platform 
 
-note:
-
-``"sys.platform != 'win32'"`` is evaluated in a dict
+NOTE: ``"sys.platform != 'win32'"`` is evaluated in a dict
 that provides ``os``, ``sys`` and ``config`` 
 (the py.test config object)
 
 The mysetup pattern 
 ==========================
 
-- glue object between test code and application
+- implemented as a funcargs 
+
+- is a glue object between test code and application
 
 - incrementally grows helper methods to avoid
   redundancy in tests 

server/conftest.py

+
+def pytest_addoption(parser):
+    parser.addoption("--scope", dest="scope", default="session", 
+        help="scope of server setup, default session")
+
+def pytest_funcarg__server(request):
+    return request.cached_setup(
+        setup=setup_server, 
+        teardown= lambda server: server.shutdown(),
+        scope=request.config.option.scope, 
+    )
+
+def setup_server():
+    server = Server()
+    server.start()
+    return server
+
+class Server:
+    def __init__(self):
+        self.alive = False
+    def start(self):
+        assert not self.alive 
+        print 
+        print ("starting server") 
+        self.alive = True
+    def shutdown(self):
+        assert self.alive 
+        print 
+        print ("shutting down server") 
+        self.alive = False

server/test_another.py

+
+def test_another_thing(server):
+    assert server.alive 

server/test_something.py

+
+def test_one(server):
+    assert server.alive
+    
+def test_two(server):
+    assert server.alive