[py-dev] RFC: draft new resource management API (v1)
holger at merlinux.eu
Thu Jun 28 10:15:45 CEST 2012
On Thu, Jun 28, 2012 at 08:47 +0100, Floris Bruynooghe wrote:
> On 27 June 2012 19:36, holger krekel <holger at merlinux.eu> wrote:
> > On Wed, Jun 27, 2012 at 16:59 +0100, Floris Bruynooghe wrote:
> >> On 27 June 2012 13:57, holger krekel <holger at merlinux.eu> wrote:
> >> > Setting resources as class attributes
> >> > -------------------------------------------
> >> >
> >> > If you want to make an attribute available on a test class, you can
> >> > use the resource_attr marker::
> >> >
> >> > @pytest.mark.resource_attr("db")
> >> > class TestClass:
> >> > def test_something(self):
> >> > #use self.db
> >> I'm not convinced of creating a special purpose mark for this.
> >> Firstly it seems like an anti-pattern in py.test to me, more like
> >> xUnit style.
> > unittest/xUnit-compat is the main idea for this new marker. It would
> > work on pytest and unittest.TestCase classes alike. It's also reminiscent
> > of Rob Collin's testscenario unittest-extension.
> >> easily done with::
> >> class TestClas(object):
> >> @classmethod
> >> def setup_class(cls, item):
> >> cls.db = item.getresource('db')
> > Not really. Here we would need to check if the setup_class()
> > accepts an item parameter and setup_class methods do not follow
> > the hook-keyword-arg-calling convention. Also passing an
> > item would be slightly arbitrary as the setup_class would
> > only be called once for all of its test items (functions).
> Oh, that will teach me to talk about an API I haven't used in a long
> time without looking it up. I thought a node (not item) was already
> passed in. Still, I think it would look nicer if it was possible to
> get to the resources API from within .setup_module(module),
> .setup_class(cls) and .setup_method(self, method) rather then needing
> a new marker for this. The first of these should not be a problem I
> guess, since it already has a node passed in. For .setup_method() the
> method argument could have an item attribute. But I guess
> .setup_class(cls) is the hardest. Would it be tricky to inspect the
> arguments as done for hooks?
setup_module/setup_class/setup_method all receive native python objects,
not collection nodes. We could stick node attributes somewhere (not sure if
on functions - they can be invoked multiple times in case of parametrization).
If we stick attributes e.g. on a pytest.current.item/classnode/... we
are doing side-effect programming - some internals will set those
attributes (and should take care to remove it to avoid
misusage/confusion) and some other places will read it. These days, i
prefer to design APIs that communicate neccesarry state directly and
to use higher-level declarations to state intents rather than do everything
through imperative programming.
/me does "import this" and sees: Although practicality beats purity ...
I am still fine to consider e. g. the introduction of a pytest.current
namespace. It could lead to make setup_X methods more powerful::
def setup_module(): # pytest accepts it to keep nose compat
db = pytest.current.modulenode.getresource("db")
The "current" namespace could be set by the respective node setup
methods. For classes it's the same idea::
cls.db = pytest.current.classnode.getresource("db")
Due to the non-declarative nature of this approach, however, i don't
see a way to rerun the testclass with multiple "db" instances.
On a side note, many Java programmers have gone from the old JUnit
approach to TestNG, see the wikipedia entries. py.test rather
goes for similar ideas as TestNG.
> >> Also, I realised this API provides for what is probably most of the
> >> cases of where I want dynamic resources:
> >> def pytest_setup_init(session):
> >> for item in my_item_generator():
> >> session.register_resource_factory(item.name, item)
> > Not sure i understand this idea. Is it intended as a mixture of
> > collection (my_item_generator) and setup (as the hook name suggests)?
> My bad for writing a bad example, I shouldn't have used the word
> "item" in there. Anyway the main point is that thanks to
> .register_resource_factory() taking the name of the resource as an
> argument I believe most, if not all, the cases where I wanted to
> create funcargs/resources without knowing what they where beforehand
> are solved.
> Debian GNU/Linux -- The Power of Freedom
> www.debian.org | www.gnu.org | www.kernel.org
More information about the Pytest-dev