python - How to test sequential operations in a python class involving class data
问题描述
Background
I have a class which performs fairly slow, complex operations on data. I want to write some tests for that class, but I'm having a hard time finding a suitable testing framework.
The class has an interface like this:
class thing():
def __init__(self, datafile):
data = read datafile
def a(self):
self.data_a = expensive(self.data)
def b(self):
self.data_b = expensive(self.data_a)
def c(self):
self.data_c = expensive(self.data_b)
etc...
The way we use this class is we usually sequentially perform the operations and analyze the results, usually at each step, often in a jupyter notebook.
Question
How should one test the methods in a class which have this structure? Is there a framework / convention for building sequential test suites?
I tried...
I tried using pytest, like so:
@pytest.mark.incremental class Test_thing(object): def setUp(self): generated_data = generate(data) generated_data.write(somewhere) self.t = thing(somewhere) def test_a(self): self.t.a() assert self.t.data_a hasProperties def test_b(self): self.t.b() assert self.t.data_b hasProperties
But
test_b
would fail withdata_a is not an attribute of thing
which is a feature, not a bug, of pytest: the tests operate in isolation from one another. But I want the opposite.I also tried unittest some time ago, but couldn't find a way to phrase my tests in that framework.
At present, I've written the tests without a testing framework, basically the pytest code from above, without pytest references, and at the end:
t = Test_thing() t.setUp() t.test_a() t.test_b() ...
Is that the best I can do?
Notes
I'm also looking for recommendations on a better title for this question
解决方案
Perhaps you could consider using the subtest
feature in the unitest
package:
import unittest
class TestExpensive(unittest.TestCase):
def setUp(self):
generated_data = generate(data)
generated_data.write(somewhere)
self.t = thing(somewhere)
def test_abc(self):
with self.subTest(status_code='a'):
self.t.a()
# Verify self.t.data_a has required properties
self.assertTrue(True)
with self.subTest(status_code='b'):
self.t.b()
# Verify self.t.data_b has required properties
self.assertTrue(False)
You can put all your expensive function calls in one test so that you can reuse any intermediate results over the course of the test. Moreover, if an error occurs, you will still be able to trace it back to the subtest that is causing the problem through the status_code
variable:
======================================================================
FAIL: test_abc (__main__.TestExpensive) (status_code='b')
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 17, in test_abc
self.assertTrue(False)
AssertionError: False is not true
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (failures=1)
推荐阅读
- r - 在用户选择下拉列表中的 R markdown / Dashboard 中从磁盘渲染图像
- javascript - 使用按钮更改 div 宽度
- sql-server - 在没有 sas/access 许可的情况下使用 SAS 从 SQL Server 读取数据
- javascript - 从模板的输入动态地形成输入,到服务中的一个函数 - Angular
- sql-server - 将 XML 解析为 (XPath, Value) 对
- reactjs - 是否可以将导出的 sass 变量列表转换为 TypeScript 联合类型(NextJs/React)
- php - 相同字符串值中的两个 bindParam
- c# - Datetimeoffset 没有给出正确的格式
- r - 是否有更快的方法对数据框中的选定列进行逐行求和?
- amazon-web-services - 如何在 .Net Core API 中安全地存储 AWS 访问密钥和秘密密钥