问题
I have some set of unittests and want to store results of each test run as YAML file for further analysis. Dump data in YAML format fit my needs in several ways. But tests belongs to different suits and results have different parent class, This is example of what I have:
>>> rz # shorthand for result
[<upstream_suite.fftest.SimpleTest testMethod=test_is_fsType_not_set>,
<upstream_suite.openfolder.UfoOpenTest testMethod=test_is_A>,
<upstream_suite.openfolder.UfoOpenTest testMethod=test_is_A_a_glyph_instance>,
<upstream_suite.openfolder.UfoOpenTest testMethod=test_is_ended_ufo>,
<upstream_suite.openfolder.UfoOpenTest testMethod=test_is_folder>,
<upstream_suite.openfolder.UfoOpenTest testMethod=test_is_fsType_eq_1>,
<upstream_suite.openfolder.UfoOpenTest testMethod=test_it_exists>]
# etc.
Each test can have its own parent class.
>>> type(rz[0]) == type(rz[1])
False
I've added my own base class for all classes with __getstate__
method, but it is not working for some reason:
>>> rz[0].__getstate__()
{'targets': ['upstream'], 'methodDoc': 'Is the OS/2 table fsType set to 0?', 'methodName': 'test_is_fsType_not_set', 'tool': 'FontForge', 'name': 'upstream_suite.fftest'}
>>> yaml.safe_dump(rz[0])
*** RepresenterError: cannot represent an object: test_is_fsType_not_set (upstream_suite.fftest.SimpleTest)
Documentations say that I can make representer for each class, so I tried it and wrote this code:
import yaml
from somepath import MyTestCase
def repr_testcase(dumper, data):
return dumper.represent_mapping(u'tag:yaml.org,2002:map', {
'methodDoc': data._testMethodDoc,
'tool': data.tool,
'name': data.name,
'methodName': data._testMethodName,
'targets': data.targets,
})
# Register representer
yaml.SafeDumper.add_representer(MyTestCase, repr_testcase)
The same time:
>>> isinstance(rz[0], MyTestCase)
True
Even after that safe_dump
isn't working. But if I made this trick, then it works and I can get result:
>>> yaml.SafeDumper.add_representer(type(rz[0]), repr_testcase)
>>> print(yaml.safe_dump(rz[0]))
methodDoc: Is the OS/2 table fsType set to 0?
methodName: test_is_fsType_not_set
name: checker.upstream_suite.fontforge_suite.fftest
targets: [upstream]
tool: FontForge
But that means that I need to register all possible occurrences, which is, well... at least, does not looks smart. Actually my real result
is more complex dictionary, tests harvested from different places, etc.
>>> for x in rz: yaml.SafeDumper.add_representer(type(x), repr_testcase)
>>> yaml.safe_dump(rz)
... here is expected result
So, question is, what I'm doing wrong with __getstate__
or how I can make work pyyaml with all instances of particular base class with only one representer registration.
回答1:
I found the way how to make this work. Short answer is that there is another way to register representer it called add_multi_representer
. So fix is:
# Change this line:
# yaml.SafeDumper.add_representer(MyTestCase, repr_testcase)
# to this line:
yaml.SafeDumper.add_multi_representer(MyTestCase, repr_testcase)
Upd. Multi representer allow to make what I was trying to achieve: register representer for base class.
来源:https://stackoverflow.com/questions/19744971/represent-instance-of-different-classes-with-the-same-base-class-in-pyyaml