I have a simple method that sets a global variable to either True or False depending on the method parameter.
This global variable is called feedback
and has a default value of False
.
When I call setFeedback('y')
the global variable will be changed to be feedback = True
.
When I call setFeedback('n')
the global variable will be changed to be feedback = False
.
Now I am trying to test this using unittest in Python:
class TestMain(unittest.TestCase):
def test_setFeedback(self):
self.assertFalse(feedback)
setFeedback('y')
self.assertTrue(feedback)
When I run this test I get the following error: AssertionError: False is not true
.
Since I know that the method works correctly, I assume that the global variables are reset somehow. However, since I am still very new to the Python environment, I don't know exactly what I am doing wrong.
I have already read an article here about mocking, but since my method changes a global variable, I don't know if mocking can solve this.
I would be grateful for suggestions.
Here is the code:
main.py:
#IMPORTS
from colorama import init, Fore, Back, Style
from typing import List, Tuple
#GLOBAL VARIABLE
feedback = False
#SET FEEDBACK METHOD
def setFeedback(feedbackInput):
"""This methods sets the feedback variable according to the given parameter.
Feedback can be either enabled or disabled.
Arguments:
feedbackInput {str} -- The feedback input from the user. Values = {'y', 'n'}
"""
#* ACCESS TO GLOBAL VARIABLES
global feedback
#* SET FEEDBACK VALUE
# Set global variable according to the input
if(feedbackInput == 'y'):
feedback = True
print("\nFeedback:" + Fore.GREEN + " ENABLED\n" + Style.RESET_ALL)
input("Press any key to continue...")
# Clear the console
clearConsole()
else:
print("\nFeedback:" + Fore.GREEN + " DISABLED\n" + Style.RESET_ALL)
input("Press any key to continue...")
# Clear the console
clearConsole()
test_main.py:
import unittest
from main import *
class TestMain(unittest.TestCase):
def test_setFeedback(self):
self.assertFalse(feedback)
setFeedback('y')
self.assertTrue(feedback)
if __name__ == '__main__':
unittest.main()
Just add # NOQA at the end of the import line that is causing the error. This tells the linter to skip that particular line.
While in many or most other programming languages variables are treated as global if not declared otherwise, Python deals with variables the other way around. They are local, if not otherwise declared. The driving reason behind this approach is that global variables are generally bad practice and should be avoided.
There are two problems with your test.
First, you use input
in your feedback
function, that will stall the test until you enter a key. You probably should mock input
. Also you may consider that the call to input
does not belong in setFeedback
(see comment by @chepner).
Second, from main import *
will not work here (apart from being bad style), because this way you create a copy of your global variable in the test module - changes in the variable itself will not be propagated to the copy. You should instead import the module, so that you will access the variable in the module.
Third (this is taken from the answer by @chepner, I had missed that), you have to make sure that the variable is at a known state at test begin.
Here is what should work:
import unittest
from unittest import mock
import main # importing the module lets you access the original global variable
class TestMain(unittest.TestCase):
def setUp(self):
main.feedback = False # make sure the state is defined at test start
@mock.patch('main.input') # patch input to run the test w/o user interaction
def test_setFeedback(self, mock_input):
self.assertFalse(main.feedback)
main.setFeedback('y')
self.assertTrue(main.feedback)
You don't need to mock anything; you just need to ensure that the global variable is in a known state before running each test. Also, using from main import *
creates a new global named feedback
in your test module, distinct from main.feedback
which setFeedback
is modifying.
import main
class TestMain(unittest.TestCase):
def setUp(self):
main.feedback = False
def test_setFeedback(self):
self.assertFalse(feedback)
main.setFeedback('y')
self.assertTrue(feedback)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With