Skip to content

[qa] Add mocks to unit tests#48

Merged
nemesifier merged 29 commits intoopenwisp:masterfrom
purhan:mock-ssh-base
May 28, 2021
Merged

[qa] Add mocks to unit tests#48
nemesifier merged 29 commits intoopenwisp:masterfrom
purhan:mock-ssh-base

Conversation

@purhan
Copy link
Copy Markdown
Contributor

@purhan purhan commented Apr 18, 2021

Replaced calls with mocks for the following unit tests:

  • tests/snmp/base.py
  • tests/snmp/openwrt.py
  • tests/snmp/airos.py

Closes #46

Comment thread tests/ssh/base.py Outdated
Comment thread tests/static/test-base-ssh.json Outdated
@purhan purhan changed the title [qa] Add mocks in base SSH unit tests [qa] Add mocks in SSH unit tests Apr 20, 2021
Copy link
Copy Markdown
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JSON formatting looks a lot better now. Thank you! Regarding the technical limitation with SNMP and in general on this subject, I understand, do what you can but if it's too much work leave it.

Let's focus your effort on achieving the goal of mocking each call to the network during tests.

@purhan purhan changed the title [qa] Add mocks in SSH unit tests [qa] Add mocks to unit tests Apr 20, 2021
Copy link
Copy Markdown
Member

@pandafy pandafy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@purhan since we are mocking tests, can we remove the need to defined test-settings.json? What will we have to achieve to be able to do that?

@purhan
Copy link
Copy Markdown
Contributor Author

purhan commented May 20, 2021

@purhan since we are mocking tests, can we remove the need to defined test-settings.json? What will we have to achieve to be able to do that?

We can hard-code some fake credentials in the tests, what do you think?

@purhan
Copy link
Copy Markdown
Contributor Author

purhan commented May 20, 2021

@pandafy Done, all tests should now run without test-settings.json.
Just run

nosetests

PS: I noticed that tests for HTTP backend are not included when you run this command.

Copy link
Copy Markdown
Member

@pandafy pandafy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PS: I noticed that tests for HTTP backend are not included when you run this command.

We will need to fix this. Adding from .http import * to tests/__init__.py seems to fix this issue. Can you confirm?

We can hard-code some fake credentials in the tests, what do you think?

Thank you for making this change.

Copy link
Copy Markdown
Member

@pandafy pandafy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@purhan since we are mocking tests, can we remove the need to defined test-settings.json? What will we have to achieve to be able to do that?

I developed some doubts regarding above review of mine. I forgot to bring it up on the call but after a quick discussion with Federico, we concluded that it be good to have the ability to run the tests with or without real device.

The current state of the patch works well to run tests without a real device. This is good for running tests in CI. So we have one part already done.

For the second part, I was thinking to have a runtests script (like other modules of openwisp) for running tests. In that script we can add a flag like --test-settings that can be used to provide path to test-settings.json.

User/Developer will be required to call the script like this

./runtests.py --test-settings=test-settings.json

On executing above command actual network calls should be executed in tests instead of mocks. This will ensure that along with the test suite, our mocks are also correct.

What do you think about this?

@purhan
Copy link
Copy Markdown
Contributor Author

purhan commented May 21, 2021

On executing above command actual network calls should be executed in tests instead of mocks. This will ensure that along with the test suite, our mocks are also correct.

What do you think about this?

I have a couple of queries related to this:

  1. What if we want to run a test separately? eg: nosetests tests.snmp.openwrt
    Then we lost this ability

Possible solution: we can make use of environment variables in settings.py which will be used in each test file.

  1. We use patches in context managers, and I could not find an inbuilt solution to disable/unpatch those patches

Possible solution: we can define a class like this:

class DisableMock(object):
        ...
        def start(self):
            pass

        def stop(self):
            pass

        def __enter__(self, *args, **kwargs):
            return self

        def __exit__(self, *args, **kwargs):
            pass

We can then use this class to disable any patch:

if settings['disable_mocks']:
        self.ssh_patcher = DisableMock()

Edit: Done in f6f4eb5

Copy link
Copy Markdown
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this PR meant to be tested with python2?

Comment thread docs/source/topics/usage.rst Outdated
Comment thread requirements-test.txt Outdated
@nemesifier nemesifier mentioned this pull request May 22, 2021
Comment thread tests/static/__init__.py Outdated
Comment thread tests/static/__init__.py Outdated
Comment thread tests/static/__init__.py Outdated
@purhan
Copy link
Copy Markdown
Contributor Author

purhan commented May 23, 2021

⚠️⚠️⚠️ @nemesisdesign @pandafy I've made an important change in 4e240ec that could've been a blunder.:warning::warning::warning:

Earlier, I was patching internal functions of netengine, eg:

# This will not detect if `next` breaks, which is an internal function of netengine
'netengine.backends.snmp.openwrt.SNMP.next'

Now:

# `nextCmd` comes from pysnmp and is not a part of netengine
'netengine.backends.snmp.base.cmdgen.CommandGenerator.nextCmd'

Now all the patched functions are from external libraries only

Comment thread tests/static/__init__.py Outdated
Comment thread tests/snmp/airos.py Outdated
Comment thread tests/snmp/airos.py Outdated
Copy link
Copy Markdown
Member

@pandafy pandafy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub was not letting me comment without posting this incomplete review. i will do a followup with another review.

Comment thread tests/snmp/airos.py Outdated
Comment thread tests/snmp/airos.py Outdated
Comment thread tests/snmp/airos.py Outdated
@nemesifier
Copy link
Copy Markdown
Member

@nemesisdesign @pandafy I've made an important change in 4e240ec that could've been a blunder.

Earlier, I was patching internal functions of netengine, eg:

# This will not detect if `next` breaks, which is an internal function of netengine
'netengine.backends.snmp.openwrt.SNMP.next'

Now:

# `nextCmd` comes from pysnmp and is not a part of netengine
'netengine.backends.snmp.base.cmdgen.CommandGenerator.nextCmd'

Now all the patched functions are from external libraries only

Yes, It may have caused issues.

@purhan purhan marked this pull request as ready for review May 26, 2021 07:27
Copy link
Copy Markdown
Member

@pandafy pandafy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good progress @purhan!

I like the SpyMock implementation. But, I believe @nemesisdesign meant decorating the tests with the patched object instead of using context manager each time like it is possible with unittest.mock.patch. See this example:

https://github.com/openwisp/openwisp-notifications/blob/e2f48f8bd6debc69064e46b1daf2252873af5734/openwisp_notifications/tests/test_ignore_object_notification.py#L27-L32

Comment thread netengine/backends/snmp/base.py Outdated
Comment thread tests/static/__init__.py
Comment thread tests/snmp/airos.py
@pandafy pandafy mentioned this pull request May 28, 2021
4 tasks
Comment thread docs/source/topics/usage.rst Outdated
Comment thread docs/source/topics/usage.rst Outdated
Copy link
Copy Markdown
Member

@pandafy pandafy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍🏼

Let's make improvements to specific things in another PR and merge this one to proceed to other things. I have opened #60 for discussing such improvements.

Deferring merge to @nemesisdesign

purhan and others added 2 commits May 28, 2021 18:46
Co-authored-by: Gagan Deep <the.one.above.all.titan@gmail.com>
Co-authored-by: Gagan Deep <the.one.above.all.titan@gmail.com>
Install test reqirements::

pip install nose
pip install -r reqirements.txt
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@purhan this should not be necessary, please double check

@nemesifier nemesifier merged commit 9cc0d09 into openwisp:master May 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[qa] Mock device output in unit tests

4 participants