Question

I'm attempting to write tests for the frontend behavior of my application, using Selenium. However, the pages I'm attempting to test get their data from Solr, and I don't want to spin up a Solr instance in order to run the tests.

I'm using py.test and py.test-django my tests, and I'm attempting to monkeypatch the views in order to make assertions about the data sent by the Selenium browser.

For example, this is a test that I would expect to fail:

def test_search(self, live_server, browser, monkeypatch):
    def mockview(request):
        from django.http import HttpResponse
        assert True == False
        return HttpResponse('Test')

    monkeypatch.setattr(project.app.views, 'search', mockview)

    browser.get(live_server.url + reverse('app:search'))

I would expect this to fail when the browser attempts to load the 'app:search' page. Instead, it loads the normal version of the page and the test succeeds.

Is there a way to get this behavior? Or is there a better way to approach these tests?

Was it helpful?

Solution

You are monkey patching the view function in the view module. Any location that has already imported that view (a reference to the function) will still hold the reference to the old (real) view function.

Django's urlconf mechanism import and configures itself with the real view, on the first request (which probably happends in another test case).

When you change the function in your views module, the urlconf will not notice it, since it already holds a reference to the old view function. Monkey patching in Python changes names/references, not functions themselves.

You are using the pytest's monkeypatch helper, but this guide in the mock library documentation provides some good info about where to apply monkey patches:

http://www.voidspace.org.uk/python/mock/patch.html#where-to-patch

In this particular case, I think your best bet is to patch the Sorl-call with static test data, rather than the view. Since you are doing a Selenium test, I think it would be very good to keep the real view. What are you actually testing if you replace the entire view?

If the view itself contains a lot of Sorl-specific code, you might want to break that code out into a separate function, which you then can easily patch out.

If you really want to change the view, I suggest you override the urlconf to point at your new view: https://pytest-django.readthedocs.org/en/latest/helpers.html#pytest-mark-urls-override-the-urlconf

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top