8

I have some code which is used in a unit test. However, the library it loads requires some data which isn't actually required for the nose-test, because that data is mocked out by the unit test. I'd like to protect the file-reads in the library so that they don't get called in the case of a nose test.

Is there an easy way to do this?

I can probably do something with sys.modules, or the initial command line, but I'd prefer something more elegant, if it exists.

Cristik
  • 24,833
  • 18
  • 70
  • 97
Brian Postow
  • 10,227
  • 14
  • 69
  • 113
  • What is a *nose test*? – wallyk Jan 04 '16 at 19:44
  • It's a specific unit-test framework. – Brian Postow Jan 04 '16 at 19:46
  • how about checking if some file exists, if it doesn't, then flag the code as 'nose-test' and prevent the load of such files. – tglaria Jan 04 '16 at 19:47
  • I don't understand - if it's mocked out, why are the reads still happening? Could you provide a [mcve]? – jonrsharpe Jan 04 '16 at 19:49
  • I can't really give an example better than "in the unit-test case I want to exclude this code" The reason it's happening is that I need a class from a library, so I'm importing the library. That library is where the data is normally read, so the reads are there, but I don't actually need them to take place in the unit test case. – Brian Postow Jan 04 '16 at 19:54
  • 1
    @BrianPostow: You shouldn't have to modify your code because of your tests. If you feel like you have to, it might suggest your design is bad. – Vincent Savard Jan 04 '16 at 19:55
  • Oh, the design is HORRIBLE. But I can't re-arrange the code until I have tests that confirm that when I re-arrange things I haven't broken anything. – Brian Postow Jan 04 '16 at 19:56
  • Having just typed that, I realize that eventually, after I refactor, hopefully the entire problem will go away, so maybe just doing something stupid with sys.modules is the best way. Leave it ugly, so that I fix ALL of it later... – Brian Postow Jan 04 '16 at 19:57
  • Too much work. eventually, I should factor out the parts that are relevant to tests into a library and data reading into a different place, but for now... meh. – Brian Postow Jan 04 '16 at 20:04
  • Instead of making your code aware of being under test or not..either mock the functionality and/or make your code composable to accept the objects to use so they can be mocked in tests. For mocking built-in functions like `open` you may check http://stackoverflow.com/questions/1289894/how-do-i-mock-an-open-used-in-a-with-statement-using-the-mock-framework-in-pyth – Montaro Feb 06 '17 at 13:17
  • This question is related: https://stackoverflow.com/questions/7341005/python-conditional-variables-based-on-whether-nosetest-is-running – Amos Egel Nov 01 '19 at 21:56

2 Answers2

10

As mentioned in comments, the structure of this code is a mess, and part of the point of the tests is to make sure that I don't break things when I refactor...

So, for now, (unless someone gives me a better answer), I'm using:

if 'nose' not in sys.modules.keys():
    <read the data>
Brian Postow
  • 10,227
  • 14
  • 69
  • 113
2

Correct approach would be to mock all code with side-effects (I'll assume that what you do not want) with empty mocks.

Given tested_module my_module:

def do_something_and_destroy_world():
    destroy_world()
    return None

Sample test file is:

import mock
import unittest

import my_module

class MyTest(unittest.TestCase):
    def testSomethingUgly(self):
        with mock.patch('my_module.destroy_world', return_value=None):
            result = do_something_and_destroy_world()
            self.assertIsNone(result)

When tests are run, assertion will be correct, and destroy_world wouldn't be called - instead it'll get replaced with empty mock with fixed return value.

Łukasz Rogalski
  • 18,883
  • 6
  • 53
  • 84
  • Nice. I don't think it would work as nicely in my current code because the messy code isn't actually in a method. Unless I can do a with mock.patch around an import, and even then it would get messy... But it's good to know what the right way to do this is in sane code... – Brian Postow Jan 04 '16 at 20:14