我应该如何自定义unittest.mock.mock_open来处理这段代码?
file: impexpdemo.py
def import_register(register_fn):
with open(register_fn) as f:
return [line for line in f]
Run Code Online (Sandbox Code Playgroud)
我第一次尝试尝试read_data.
class TestByteOrderMark1(unittest.TestCase):
REGISTER_FN = 'test_dummy_path'
TEST_TEXT = ['test text 1\n', 'test text 2\n']
def test_byte_order_mark_absent(self):
m = unittest.mock.mock_open(read_data=self.TEST_TEXT)
with unittest.mock.patch('builtins.open', m):
result = impexpdemo.import_register(self.REGISTER_FN)
self.assertEqual(result, self.TEST_TEXT)
Run Code Online (Sandbox Code Playgroud)
这失败了,大概是因为代码不使用read,readline或readlines.unittest.mock.mock_open 的文档说:"read_data是要返回的文件句柄的read(),readline()和readlines()方法的字符串.对这些方法的调用将从read_data中获取数据,直到它耗尽为止这些方法的模拟非常简单.如果你需要更多地控制你要测试代码的数据,你需要自己定制这个模拟.默认情况下,read_data是一个空字符串."
由于文件没有给出暗示上会需要什么样定制我试图return_value和side_effect.都没有奏效.
class TestByteOrderMark2(unittest.TestCase):
REGISTER_FN = 'test_dummy_path'
TEST_TEXT = ['test text 1\n', 'test text 2\n']
def test_byte_order_mark_absent(self):
m = unittest.mock.mock_open()
m().side_effect = self.TEST_TEXT
with unittest.mock.patch('builtins.open', m):
result = impexpdemo.import_register(self.REGISTER_FN) …Run Code Online (Sandbox Code Playgroud) 什么是正确的类型提示x = []?
我的 PyCharm 编辑器中的类型检查器将此标记为错误:
labelframes: List[ttk.LabelFrame] = []
Run Code Online (Sandbox Code Playgroud)
'Optional' 不是一个选项,如:
labelframes: List[Optional[ttk.LabelFrame]] = []
Run Code Online (Sandbox Code Playgroud)
因为文档typing.Optional说明这相当于:
labelframes: List[Union[ttk.LabelFrame, None]] = []
Run Code Online (Sandbox Code Playgroud)
并且[None]不是[]。
我应该提到 PyCharm 也不喜欢这样:
labelframes: List[Union[ttk.LabelFrame, None]] = [None]
Run Code Online (Sandbox Code Playgroud)
无论我尝试什么类型的提示。PyCharm 将其标记为错误,“预期在此处返回我的类型提示,但没有返回”,因此我尝试了:
labelframes: Optional[List[ttk.LabelFrame, None]] = []
Run Code Online (Sandbox Code Playgroud)
那没有用。
我知道 PEP 526 有许多遵循以下模式的示例:
x: List[str] = []
Run Code Online (Sandbox Code Playgroud) 我试图找出如何在对话框窗口中单元测试绑定命令.我正在尝试使用tkinter event_generate.它不像我期望的那样工作.对于这个StackOverflow问题,我通过一次调用设置了一些代码event_generate.有时这条线有效,有时就好像线条甚至不存在一样.
对话框__init__方法中的绑定如下所示:
self.bind('<BackSpace>', #Print "BackSpace event generated."
lambda event: print(event.keysym, 'event generated.'))
Run Code Online (Sandbox Code Playgroud)
对话框中的任何操作都将回调其终止方法(该对话框基于Frederik Lundh在"Tkinter简介"中的对话框示例.)
def terminate(self, event=None):
print('terminate called') # Make sure we got here and the next line will be called
self.event_generate('<BackSpace>')
self.parent.focus_set()
self.destroy()
Run Code Online (Sandbox Code Playgroud)
使用下面的代码调用对话框时,任何用户操作都将最终调用terminate.在每种情况下"终止被叫"和"BackSpace事件生成".显示.这证明了对event_generate的调用是正确设置的.
parent = tk.Tk()
dialog = Dialog(parent)
dialog.wait_window()
Run Code Online (Sandbox Code Playgroud)
如果它是相关的,我应该提到我已经将Lundh的调用self.wait_window从他的对话框的__init__方法移动到调用者.虽然这打破了对话框的整洁封装,但似乎有必要进行自动化的单元测试.否则,unittest将显示对话框并停止等待用户输入.我不喜欢这个解决方案,但我不知道任何替代方案.
我遇到的问题是何时wait_window被直接调用terminate方法替换.这是我希望在单元测试中可以做的事情,即在不运行tkinter的mainloop或wait_window的情况下测试我的GUI代码.
parent = tk.Tk()
dialog = Dialog(parent)
dialog.terminate()
Run Code Online (Sandbox Code Playgroud)
这只打印"终止被叫"并且不打印"BackSpace事件生成".呼叫event_generate似乎没有效果.如果我在调试器中跟随调用,我可以看到event_generate()正在使用正确的参数调用tkinter .self = {Dialog} .99999999, sequence = …
在下面的代码中,该astuple函数正在执行数据类的类属性的深层复制。为什么它产生的结果与函数不同my_tuple?
import copy
import dataclasses
@dataclasses.dataclass
class Demo:
a_number: int
a_bool: bool
classy: 'YOhY'
def my_tuple(self):
return self.a_number, self.a_bool, self.classy
class YOhY:
def __repr__(self):
return (self.__class__.__qualname__ + f" id={id(self)}")
why = YOhY()
print(why) # YOhY id=4369078368
demo = Demo(1, True, why)
print(demo) # Demo(a_number=1, a_bool=True, classy=YOhY id=4369078368)
untrupled = demo.my_tuple()
print(untrupled) # YOhY id=4369078368
trupled = dataclasses.astuple(demo)
print(trupled) # YOhY id=4374460064
trupled2 = trupled
print(trupled2) # YOhY id=4374460064
trupled3 = copy.copy(trupled)
print(trupled3) # YOhY id=4374460064
trupled4 …Run Code Online (Sandbox Code Playgroud) 我想测试一下功能is_myclass。请帮助我了解如何编写成功的测试。
def is_myclass(obj):
"""This absurd stub is a simplified version of the production code."""
isinstance(obj, MyClass)
MyClass()
Run Code Online (Sandbox Code Playgroud)
文档
unittest.mock 的 Python 文档说明了解决该isinstance问题的三种方法:
spec参数设置为真实的类。__class__属性。spec在真实类的补丁中使用。
__class__通常,
__class__对象的属性将返回其类型。对于具有规范的模拟对象,__class__返回规范类。这允许模拟对象通过 isinstance() 测试它们正在替换/伪装为的对象:Run Code Online (Sandbox Code Playgroud)>>> mock = Mock(spec=3) >>> isinstance(mock, int) True
__class__可分配给,这允许模拟通过isinstance()检查而不强迫您使用规范:Run Code Online (Sandbox Code Playgroud)>>> mock = Mock() >>> mock.__class__ = dict >>> isinstance(mock, dict) True[...]
如果您使用
specorspec_set并且patch()正在替换一个类,那么创建的模拟的返回值将具有相同的规范。Run Code Online (Sandbox Code Playgroud)>>> Original = Class >>> patcher …
前两个函数display_pane_1和template_1很容易在该方法中进行测试test_1。我想将这两个函数重构为一个函数display_pane_2。
lambdademo.py:
def display_pane_1():
display_register(template_1)
def template_1():
return 'hello mum'
def display_pane_2():
display_register(lambda: 'hello mum')
def display_register(template):
print(template())
Run Code Online (Sandbox Code Playgroud)
test_lambdademo.py
import unittest
import unittest.mock as mock
import lambdademo
class TestLambda1(unittest.TestCase):
def setUp(self):
p = mock.patch('lambdademo.display_register')
self.mock_display_register = p.start()
self.addCleanup(p.stop)
def test_1(self):
lambdademo.display_pane_1()
self.mock_display_register.assert_called_with(lambdademo.template_1)
def test_2(self):
lambdademo.display_pane_2()
self.mock_display_register.assert_called_with('????????')
Run Code Online (Sandbox Code Playgroud)
你能帮我写一个有效的测试吗display_pane_2?我想测试完整的 lambda 表达式,即lambda x: 'hell mum'应该失败。
我尝试了两种解决方案。
第一个选项是 的简单副本,用 的模拟test_1替换 的参数。我在手册中找不到任何建议我应该如何模拟像 lambda 这样的表达式的内容。如果手册中有的话请告诉我在哪里。lambdademo.template_1lambda
我的第二个选择是在 Stack Overflow 和互联网上进行了更广泛的搜索。缺少“python 表达式单元测试”、“python …
open通过加薪进行FileNotFoundError模拟测试AttributeError: __exit__。为什么会发生这种情况以及我可以采取什么措施来解决它?
以下代码打开一个简单的文本文件。如果文件丢失,它会生成一个默认值。它已经通过定期运行进行了检查,并且看起来运行良好。
so_main.py
import os
import so_config
def load_savelocation():
path = os.path.join(so_config.ROOT, so_config.SAVELOCATION_FN)
savelocation_path = os.path.normpath(path)
try:
with open(savelocation_path) as f:
so_config.SAVELOCATION_PATH = f.readline()
except FileNotFoundError:
so_config.SAVELOCATION_PATH = so_config.ROOT
Run Code Online (Sandbox Code Playgroud)
so_config.py
import os
ROOT, _ = os.path.split(__file__)
SAVELOCATION_PATH = None
SAVELOCATION_FN = 'savelocation.ini'
Run Code Online (Sandbox Code Playgroud)
单元测试则是另一回事。我嘲笑了open中的命令so.main。test_so_main.py有两项测试:一项用于正常打开存在的文件,第二项用于测试处理FileNotFoundError。
常规文件打开的第一次测试test_read_path_from_disk_file_into_config_py工作正常。
FileNotFoundError第二个测试失败,因为AttributeError: __exit__. 我可以设置self.mock_open.return_value为FileNotFoundError或我可以将其设置为'garbage'。这没有什么区别。
测试so_main.py
import unittest
import unittest.mock as mock
import …Run Code Online (Sandbox Code Playgroud) python ×6
unit-testing ×4
mocking ×3
python-3.x ×3
iteration ×1
lambda ×1
python-mock ×1
tkinter ×1
try-except ×1
type-hinting ×1
typing ×1