2

How can I write a unit test for the following function:

def version_switch():
    if sys.version_info.major < 3:
        print('not python 3')
    else:
        print('python 3')

My first thought was mocking sys.version_info.major but as it is a read only attribute it will not do.

To be sure: I do run my test suite under py3 and py2 using tox. however, each run will only check one code path. The actual function does not use any language specific features. Should I look for alternative ways to determine the version, ones that are easier to mock?

3
  • "the actual function does not use any language specific features" -- Then what does it do? Why look at sys.version_info in the first place? Commented Jun 24, 2016 at 22:32
  • Are you asking how to get 100% code coverage in each version? Commented Jun 24, 2016 at 22:35
  • @SamDufel I asked because I don't like not covering without good reason. I don't need to see a 100, but I want to know that I didn't take shortcuts. Commented Jun 24, 2016 at 22:56

2 Answers 2

7

You may not be able to swap out the value of major on sys.version_info, but you can swap out the value of version_info on sys:

Python 2.7.10 (default, Oct 23 2015, 19:19:21) 
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> import mock
>>> with mock.patch.object(sys, 'version_info') as v_info:
...   v_info.major = 3
...   print(sys.version_info.major)
... 
3

Note that I'm using python2.7, but I convinced sys to tell me that I'm using python3.x.

Sign up to request clarification or add additional context in comments.

1 Comment

I was getting AttributeError: sys does not have the attribute 'version_info' because I accidentally was using 'sys' rather than sys so thank you.
1

however, each run will only check one code path

So?

You don't care what the Python 3 code path would do if you ran it on Python 2, or vice versa. There's no need to test that. Just check that the output correctly corresponds to the Python version you're running on.

3 Comments

I disagree. From a unit test point of view the function foes not need to care what the value in sys.version_info represents. Something that should be reflected by the fact that it is covered both ways.
@Elbenfreund: From a unit test point of view, the unit under test needs to determine what Python version it's running on, and you need to test that it does that. If you want to, say, test the function's ability to compare the major attribute of some object to 3, you might want to refactor this function to use a helper function that takes a version info object and compares its major attribute to 3. Then you can test the helper straightforwardly.
What you're asking for here sounds a lot like trying to test the base case code path of a recursive Fibonacci function for fib(5), or test the recursive case code path for fib(1).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.