Python 单元测试正确设置全局变量
Python unittest setting a global variable correctly
我有一个简单的方法,可以根据方法参数将全局变量设置为 True 或 False。
这个全局变量叫做feedback
,默认值为False
。
当我调用 setFeedback('y')
时,全局变量将更改为 feedback = True
。
当我调用 setFeedback('n')
时,全局变量将更改为 feedback = False
.
现在我正在尝试使用 Python:
中的单元测试来测试它
class TestMain(unittest.TestCase):
def test_setFeedback(self):
self.assertFalse(feedback)
setFeedback('y')
self.assertTrue(feedback)
当我 运行 这个测试时,我得到以下错误:AssertionError: False is not true
。
因为我知道该方法工作正常,所以我假设全局变量以某种方式被重置。但是,由于我对 Python 环境还很陌生,所以我不知道我做错了什么。
我已经在这里阅读了一篇关于 mocking 的文章,但是由于我的方法更改了一个全局变量,所以我不知道 mocking 是否可以解决这个问题。
我将不胜感激。
代码如下:
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()
你的测试有两个问题。
首先,您在 feedback
函数中使用 input
,这将暂停测试,直到您输入密钥。你可能应该嘲笑 input
。此外,您可能会认为对 input
的调用不属于 setFeedback
(请参阅@chepner 的评论)。
其次,from main import *
在这里不起作用(除了 bad style),因为这样您可以在测试模块中创建全局变量的副本 - 变量本身的更改不会传播到副本。您应该改为导入模块,以便访问模块中的变量。
第三(这是来自@chepner 的回答,我错过了),你必须确保变量在测试开始时处于已知状态。
这是应该起作用的:
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)
你不需要模拟任何东西;您只需要确保全局变量在 运行 每次测试之前处于已知状态。此外,使用 from main import *
在您的测试模块中创建一个名为 feedback
的 new 全局,不同于 setFeedback
正在修改的 main.feedback
。
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)
我有一个简单的方法,可以根据方法参数将全局变量设置为 True 或 False。
这个全局变量叫做feedback
,默认值为False
。
当我调用 setFeedback('y')
时,全局变量将更改为 feedback = True
。
当我调用 setFeedback('n')
时,全局变量将更改为 feedback = False
.
现在我正在尝试使用 Python:
中的单元测试来测试它class TestMain(unittest.TestCase):
def test_setFeedback(self):
self.assertFalse(feedback)
setFeedback('y')
self.assertTrue(feedback)
当我 运行 这个测试时,我得到以下错误:AssertionError: False is not true
。
因为我知道该方法工作正常,所以我假设全局变量以某种方式被重置。但是,由于我对 Python 环境还很陌生,所以我不知道我做错了什么。
我已经在这里阅读了一篇关于 mocking 的文章,但是由于我的方法更改了一个全局变量,所以我不知道 mocking 是否可以解决这个问题。
我将不胜感激。
代码如下:
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()
你的测试有两个问题。
首先,您在 feedback
函数中使用 input
,这将暂停测试,直到您输入密钥。你可能应该嘲笑 input
。此外,您可能会认为对 input
的调用不属于 setFeedback
(请参阅@chepner 的评论)。
其次,from main import *
在这里不起作用(除了 bad style),因为这样您可以在测试模块中创建全局变量的副本 - 变量本身的更改不会传播到副本。您应该改为导入模块,以便访问模块中的变量。
第三(这是来自@chepner 的回答,我错过了),你必须确保变量在测试开始时处于已知状态。
这是应该起作用的:
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)
你不需要模拟任何东西;您只需要确保全局变量在 运行 每次测试之前处于已知状态。此外,使用 from main import *
在您的测试模块中创建一个名为 feedback
的 new 全局,不同于 setFeedback
正在修改的 main.feedback
。
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)