Code Monkey home page Code Monkey logo

Comments (3)

nicoddemus avatar nicoddemus commented on May 10, 2024

Hi @baudren!

I can reproduce the problem, thanks for the detailed explanation.

I checked that the mocker fixture is calling mock.patch.object at the appropriate places, so that seems fine.

I dug down into the source code for unittest.mock and noticed that the line that actually installs the mock into the target object sometimes fail:

# contents of mock.py:1239
setattr(self.target, self.attribute, new_attr)

In the first mocker.patch.object call from your example, this line is executed and correctly replaces QMessage.question staticmethod by a new MagicMock instance. The second time this code is executed it sometimes fails to replace the existing MagicMock instance by the new one, which can be verified by adding print(getattr(self.target, self.attribute)) right after it.

Changing your code slightly to add another level of indirection, like this:

class Simple(QFrame):

    def query(self, notebook):
        reply = self._question(notebook, self)
        ...

    @staticmethod
    def _question(notebook, parent):
        return QMessageBox.question(
            parent, 'Message', 'Deleting %s, are you sure?' % notebook,
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

def test_Qt(qtbot, mocker):
   ...
   mocker.patch.object(simple, '_question',
                        return_value=QMessageBox.No))

Seems to fix the problem. My bet is that PySide's bindings might be at fault here when one tries to change an staticmethod attribute of a class.

Having said all that, an easy workaround is for you to reuse the mocked object:

def test_Qt(qtbot, mocker):
    simple = Simple()
    qtbot.addWidget(simple)

    question = mocker.patch.object(QMessageBox, 'question',
                        return_value=QMessageBox.No)
    simple.query('toto')
    assert simple.answer == 'no'

    question.return_value = QMessageBox.Yes
    simple.query('toto')
    assert simple.answer == 'yes'

Answering your questions:

Is it somehow forbidden to use two mock.patch.object statements in a row, without doing some sort of cleaning?

Shouldn't be necessary, but if you must you can use mocker.stopall().

And that it is pure luck that this works under 2.7?

No, it seems a consistent failure.

It seemed to me that the original mock module uses a Python
with ...: syntax, probably for house cleaning. There is no such thing in this
module, right?

No, there isn't... if you want to use a with statement, you can use mock directly. This was the motivation for changing the fixture name to mocker, so you can use both in your tests if needed.

Or is it something due to the fact that now mock is integrated in py.test, since Python 3.3?

Don't think so, I believe it is the same source code. (I believe you meant Python above, of course 😁)

Thanks for the detailed explanation and bug report!

Cheers, 🍻

from pytest-mock.

baudren avatar baudren commented on May 10, 2024

Thanks, one more time, for the detailed explanation. I will go along the route of reusing the object - I should have thought about that myself. So you would say it is rather a problem directly with PySide, not with mock?

Best,

from pytest-mock.

nicoddemus avatar nicoddemus commented on May 10, 2024

Seems like it, this test fails for me in Python 3, but works in Python 2:

def test_foo():
    for i in range(10):
        QtGui.QMessageBox.question = i
        assert QtGui.QMessageBox.question == i

Cheers!

from pytest-mock.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.