================================== Frequently Asked Questions ================================== .. contents:: :local: :depth: 2 On naming, nose and magic ============================ Why the ``py`` naming? what is it? ------------------------------------ Because the name was kind of available and there was the idea to have the package evolve into a "standard" library kind of thing that works cross-python versions and is not tied to a particular CPython revision or its release cycle. Clearly, this was ambitious and the naming has maybe haunted the project rather than helping it. There may be a project name change and possibly a split up into different projects sometime. Why the ``py.test`` naming? ------------------------------------ the py lib contains other command line tools that all share the ``py.`` prefix which makes it easy to use TAB-completion on the shell. Another motivation was to make it obvious where testing functionality for the ``py.test`` command line tool is: in the ``py.test`` package name space. What's the relation to ``nosetests``? ---------------------------------------- py.test and nose_ share basic philosophy when it comes to running Python tests. In fact, with py.test-1.0.1 it is easy to run many test suites that currently work with ``nosetests``. nose_ was created as a clone of ``py.test`` when it was in the ``0.8`` release cycle so some of the newer features_ introduced with py.test-1.0 have no counterpart in nose_. .. _nose: http://somethingaboutorange.com/mrl/projects/nose/0.11.1/ .. _features: test/features.html What's all this "magic" with py.test? ---------------------------------------- "All this magic" usually boils down to two issues: * There is a special tweak to importing: `py/__init__.py`_ contains a dictionary which maps the importable ``py.*`` namespaces to objects in files. When looking at the project source code you see imports like ``from py.__.test.session import Session``. The the double ``__`` underscore indicates the "normal" python filesystem/namespace coupled import, i.e. it points to ``py/test/session.py``'s ``Session`` object. However, from the outside you use the "non-underscore" `py namespaces`_ so this distinction usually only shows up if you hack on internal code or see internal tracebacks. * when an ``assert`` fails, py.test re-interprets the expression to show intermediate values. This allows to use the plain ``assert`` statement instead of the many methods that you otherwise need to mimick this behaviour. This means that in case of a failing assert, your expressions gets evaluated *twice*. If your expression has side effects the outcome may be different. If the test suddenly passes you will get a detailed message. It is good practise, anyway, to not have asserts with side effects. ``py.test --nomagic`` turns off assert re-intepretation. Other than that, ``py.test`` has bugs or quirks like any other computer software. In fact, it has a *strong* focus on running robustly and has over a thousand automated tests for its own code base. .. _`py namespaces`: index.html .. _`py/__init__.py`: http://bitbucket.org/hpk42/py-trunk/src/1.0.x/py/__init__.py function arguments and parametrized tests =============================================== .. _`why pytest_pyfuncarg__ methods?`: Why the ``pytest_funcarg__*`` name for funcarg factories? --------------------------------------------------------------- When experimenting with funcargs an explicit registration mechanism was considered. But lacking a good use case for this indirection and flexibility we decided to go for `Convention over Configuration`_ and allow to directly specify the factory. Besides removing the need for an indirection it allows to "grep" for ``pytest_funcarg__MYARG`` and will safely find all factory functions for the ``MYARG`` function argument. It helps to alleviates the de-coupling of function argument usage and creation. .. _`Convention over Configuration`: http://en.wikipedia.org/wiki/Convention_over_Configuration Can i yield multiple values from a factory function? ----------------------------------------------------- There are two reasons why yielding from a factory function is not possible: * Calling factories for obtaining test function arguments is part of setting up and running a test. At that point it is not possible to add new test calls to the test collection anymore. * If multiple factories yielded values there would be no natural place to determine the combination policy - in real-world examples some combinations often should not run. Use the `pytest_generate_tests`_ hook to solve both issues and implement the `parametrization scheme of your choice`_. .. _`pytest_generate_tests`: test/funcargs.html#parametrizing-tests .. _`parametrization scheme of your choice`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/