Im practising with unit testing and nose tests from a simple game and I have a section of the game that has dice rolls with random.randint which I need to test. I have been following this article on how to test random events with mock
http://www.jjinux.com/2014/01/python-lightning-quick-introduction-to.html
Im getting this error when I run nosetests though
ERROR: tests.ex47_tests.test_dice_roll
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1297, in patched
arg = patching.__enter__()
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1353, in __enter__
self.target = self.getter()
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1520, in <lambda>
getter = lambda: _importer(target)
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1210, in _importer
thing = _dot_lookup(thing, comp, import_path)
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1199, in _dot_lookup
__import__(import_path)
ImportError: No module named random
I have imported random so not sure why that isn't working or is this something to do with mock?
Here is the portion of code from the game file and tests file (Ive not put all code here as I dont think needed)
game.py
class Intro(Rooms):
def enter(self):
print "Intro room"
print "You see the Gothon, you have to fight him!"
def dice_roll_fight(self):
print 'DICE ROLL'
dice_roll = randint(1,6)
print "You rolled a ", dice_roll
if dice_roll <= 2:
return 'death'
elif dice_roll >= 3:
return 'starter'
else:
print "ERROR try again"
ex47_tests.py
from nose.tools import *
from ex47.game import Intro
from mock import mock
import random
@mock.patch('ex47.game.random.randint')
def test_dice_roll(randint_mock):
randint_mock.return_value = 1
assert_equal(game.dice_roll_fight(), 'death')
@mock.patch('ex47.game.random.randint')
def test_dice_roll(randint_mock):
randint_mock.return_value = 2
assert_equal(game.dice_roll_fight(), 'death')
@mock.patch('ex47.game.random.randint')
def test_dice_roll(randint_mock):
randint_mock.return_value = 3
assert_equal(game.dice_roll_fight(), 'starter')
Based on how are calling rand_int
in your Intro
class, you are probably importing this way:
from random import randint
In that case, your patching should be as such:
@mock.patch('ex47.game.randint')
The way you are patching:
@mock.patch('ex47.game.random.randint')
Indicates that you are importing like this:
import random
Furthermore, I see a few of problems in your test code.
You are importing random in your tests. You should not need to do this. You are patching correctly (patching with respect to what you are testing), so you do not need to import random since you will be properly patching your random method with respect to your game
module.
It seems like you are trying to call your methods without actually instantiating your class. If you haven't already, you should set up your test as:
class ThisIsMyTest(unittest.TestCase):
def setUp(self):
self.game = Intro()
Your test methods are all named the same. This will end up only running one test and you will not be receiving the other results you want to test.
With the above three mentions in mind, the following code should suffice to help with your unit testing:
import unittest
from nose.tools import assert_equal
from game import Intro
from mock import mock
class GameTest(unittest.TestCase):
def setUp(self):
self.game = Intro()
@mock.patch('game.randint')
def test_dice_roll_one(self, randint_mock):
randint_mock.return_value = 1
from nose.tools import assert_equal
assert_equal(self.game.dice_roll_fight(), 'death')
@mock.patch('game.randint')
def test_dice_roll_two(self, randint_mock):
randint_mock.return_value = 2
assert_equal(self.game.dice_roll_fight(), 'death')
@mock.patch('game.randint')
def test_dice_roll_three(self, randint_mock):
randint_mock.return_value = 3
assert_equal(self.game.dice_roll_fight(), 'starter')
if __name__ == '__main__':
unittest.main()