[pytest-dev] Parametrized autouse fixtures

Thomas De Schampheleire patrickdepinguin at gmail.com
Tue Mar 13 18:05:02 EDT 2018


Thanks a lot, this did help me very well!

/Thomas

2018-03-12 22:16 GMT+01:00 Bruno Oliveira <nicoddemus at gmail.com>:
> Hi Thomas,
>
> It seems the problem is that you are mixing xunit-style fixtures (by
> implementing a setup_class classmethod) and pytest-style fixtures: they
> currently don’t play well together, setup_* methods execute before all other
> fixtures (see #517). There are plans to fix that, but this scheduled for 3.6
> only.
>
> But there’s an easy workaround, just change your “setup_class” method into a
> proper fixture instead:
>
> class TestArchivesTestCaseMixin:
>
>     @classmethod
>     @pytest.fixture(autouse=True, params=['hg', 'git'], scope='class')
>     def _configure_backend(cls, request):
>         backend_alias = request.param
>         Backend = vcs.get_backend(backend_alias)
>         ...
>
> Hope that helps.
>
> Cheers,
> Bruno.
>
>
> On Mon, Mar 12, 2018 at 5:48 PM Thomas De Schampheleire
> <patrickdepinguin at gmail.com> wrote:
>>
>> Hello,
>>
>> The Kallithea project is a repository hosting and review system,
>> currently supporting git and hg. We currently have some test cases
>> that need to be run for these two version control systems.
>>
>> Previously this was done with some Python magic, which was now
>> simplified and made more explicit in commit:
>>
>> https://kallithea-scm.org/repos/kallithea/changeset/45a281a0f36ff59ffaa4aa0107fabfc1a6310251
>>
>> but I assume it can be made more automatic with pytest fixtures. I was
>> thinking to use an autouse, parametrized fixture to set the backend to
>> 'hg' and 'git' respectively. But I can't make it work.
>>
>> Here is the change I did on top of the mentioned commit:
>>
>> diff --git a/kallithea/tests/vcs/base.py b/kallithea/tests/vcs/base.py
>> --- a/kallithea/tests/vcs/base.py
>> +++ b/kallithea/tests/vcs/base.py
>> @@ -5,6 +5,7 @@ InMemoryChangeset class is working prope
>>  import os
>>  import time
>>  import datetime
>> +import pytest
>>
>>  from kallithea.lib import vcs
>>  from kallithea.lib.vcs.nodes import FileNode
>> @@ -27,6 +28,11 @@ class _BackendTestMixin(object):
>>      """
>>      recreate_repo_per_test = True
>>
>> +    @pytest.fixture(autouse=True,
>> +                    params=['hg', 'git'])
>> +    def set_backend_alias(cls, request):
>> +        cls.backend_alias = request.param
>> +
>>      @classmethod
>>      def get_backend(cls):
>>          return vcs.get_backend(cls.backend_alias)
>> diff --git a/kallithea/tests/vcs/test_archives.py
>> b/kallithea/tests/vcs/test_archives.py
>> --- a/kallithea/tests/vcs/test_archives.py
>> +++ b/kallithea/tests/vcs/test_archives.py
>> @@ -14,7 +14,7 @@ from kallithea.tests.vcs.base import _Ba
>>  from kallithea.tests.vcs.conf import TESTS_TMP_PATH
>>
>>
>> -class ArchivesTestCaseMixin(_BackendTestMixin):
>> +class TestArchivesTestCaseMixin(_BackendTestMixin):
>>
>>      @classmethod
>>      def _get_commits(cls):
>> @@ -95,11 +95,3 @@ class ArchivesTestCaseMixin(_BackendTest
>>      def test_archive_prefix_with_leading_slash(self):
>>          with pytest.raises(VCSError):
>>              self.tip.fill_archive(prefix='/any')
>> -
>> -
>> -class TestGitArchive(ArchivesTestCaseMixin):
>> -    backend_alias = 'git'
>> -
>> -
>> -class TestHgArchive(ArchivesTestCaseMixin):
>> -    backend_alias = 'hg'
>>
>>
>>
>> but when running this I get:
>>
>> $  pytest kallithea/tests/vcs/test_archives.py
>> Test session starts (platform: linux2, Python 2.7.14, pytest 3.4.2,
>> pytest-sugar 0.9.1)
>> benchmark: 3.1.1 (defaults: timer=time.time disable_gc=False
>> min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10
>> warmup=False warmup_iterations=100000)
>> rootdir: /home/tdescham/repo/contrib/kallithea/kallithea-review,
>> inifile: pytest.ini
>> plugins: sugar-0.9.1, localserver-0.4.1, benchmark-3.1.1
>>
>>
>> ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
>> ERROR at setup of TestArchivesTestCaseMixin.test_archive_zip[hg]
>> ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
>> kallithea/tests/vcs/base.py:70: in setup_class
>>     Backend = cls.get_backend()
>> kallithea/tests/vcs/base.py:38: in get_backend
>>     return vcs.get_backend(cls.backend_alias)
>> E   AttributeError: type object 'TestArchivesTestCaseMixin' has no
>> attribute 'backend_alias'
>>
>>
>>                                                         7% ▊
>>
>> ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
>> ERROR at setup of TestArchivesTestCaseMixin.test_archive_zip[git]
>> ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
>> kallithea/tests/vcs/base.py:70: in setup_class
>>     Backend = cls.get_backend()
>> kallithea/tests/vcs/base.py:38: in get_backend
>>     return vcs.get_backend(cls.backend_alias)
>> E   AttributeError: type object 'TestArchivesTestCaseMixin' has no
>> attribute 'backend_alias'
>>
>>
>>                                                        14% █▌
>>
>> [..]
>>
>>
>>
>> So the parametrization seems to work because each test is run twice,
>> but I can't seem to find the right way to set the backend_alias, such
>> that a later call from a classmethod works correctly.
>>
>> I found some possibly useful magic by nicoddemus but could not make
>> that work either:
>> https://github.com/pytest-dev/pytest/issues/2618#issuecomment-318519875
>>
>> Is it possible to achieve what I want, without changing each test
>> method to take a fixture explicitly?
>>
>> Thanks,
>> Thomas
>> _______________________________________________
>> pytest-dev mailing list
>> pytest-dev at python.org
>> https://mail.python.org/mailman/listinfo/pytest-dev


More information about the pytest-dev mailing list