In Pytest, does conftest.py at the root level get overridden by conftests deeper in the tree?

Viewed 303

Our current project has a project tree with a conftest.py at the root level of the tests like below:

Tests
   test_folder_1
   test_folder_2
   conftest.py

This root level conftest.py imports most of our fixtures at session and class levels. But in test_folder_1, we have another conftest.py that we want to override some of those class level fixtures and turn them function-scoped.

I was under the impression that this would work and has been working, but now I'm getting errors with some of these: You tried to access the 'function' scoped fixture 'new_primary_contact' with a 'class' scoped request object

If this is not how to override fixtures from conftest.py, is there another way? It could be another error, but I really want to know if conftest.py's further in the tree actually override high level ones. Thanks for any help!

EDIT: Here is an minimal example of my code:

Root level conftest.py:

from automation.Fixtures.ClassScope import config, api_client, new_related_contact, \
    new_primary_contact, auto_clean_contacts_helper as contacts_helper, create_contact_payload, document_helper

In my lower level test, in root/feature_1 I have something like this in a conftest.py:

from automation.Fixtures.FunctionScope import new_related_contact, \
    new_primary_contact, auto_clean_contacts_helper as contacts_helper, create_contact_payload, document_helper

I was just wanting to override certain fixtures, so my function level tests would not use class scope.

Here is a test example using them in root/feature_1/Tests:

class TestDeleteRelatedContactWorkflow:
    def test__remove_related_contact(self, authenticated_chrome_driver, config, new_primary_contact, new_related_contact, new_contact_proposal, contacts_helper):
        primary_contact_name = new_primary_contact["display_name"]
        related_contact_name = new_related_contact["display_name"]
        related_contact_id = new_related_contact["ContactId"]
        document_id = new_contact_document["id"]

        web_nav = WebNavigation(authenticated_chrome_driver, config)
        web_nav.navigate_to_document_view_page(document_id)
        ...
        response = contacts_helper.delete_contact(related_contact_id)
        assert response["IsSuccess"] is True, f'Deletion of contact "{related_contact_name}" not successful.'
        assert response["StatusCode"] == 200, 'Status code should == 200 when deleting contact.'

The test fails before it logs in and after the webdriver/browser initiates (names changed to protect code)

test setup failed
ScopeMismatch: You tried to access the 'function' scoped fixture 'new_primary_contact' with a 'class' scoped request object, involved factories
root/Fixtures/ClassScope/class_scoped_document_fixtures.py:19:  def new_document_payload(config, new_primary_contact)
root/Fixtures/FunctionScope/function_scoped_contacts_fixtures.py:85:  def new_primary_contact(contacts_helper, create_contact_payload)
1 Answers

I would add conftest.py to ROOT folder, only if I was 100% sure all my tests are using all imported fixtures there, otherwise you are just slowing down automation execution which is critical.

I have tested the following:

Tests
   conftest.py
   test_folder_1
        conftest.py
   test_folder_2

Both conftest.py files had fixture function with the same name. in test_folder_1/conftest.py - I have set scope="function" and returned different value compared to the same fixture in Tests/conftest.py (which had scope="class").

In a test under test_folder_1, I was able to use the updated fixture from test_folder_1/conftest.py. I am not able to apply this fixture on a class, as the scope changed.

Related