Python PyCharm 上的单元测试有时会在不更改 SUT 中的任何代码的情况下通过

Python unittest on PyCharm sometimes passes without changing any code in SUT

这个问题是我遇到的第一个问题。我有一个 class 和相应的单元测试。测试 passes/fails 随机,在被测 class 上没有任何变化。我的意思是我按下 shift+F10 并立即再次按下它。一个通过,一个失败。

这是class(虽然看起来有点脏,请见谅)

class XmlSerializer:

    def __init__(self, int_repr = 'int', str_repr = 'str'):
        """@int_repr: integer type representation (default: 'int')
        @str_repr : string type representation (default: 'str')"""
        self.xml_result = []
        self.__int_repr = int_repr
        self.__str_repr = str_repr

    def serialize(self, element):
        self.xml_result = []
        self.__recurse2(element, indent='')
        return ''.join(self.xml_result)

    def __recurse2(self, element, indent):
        if isinstance(element, int):
            self.xml_result += indent + '\t<' + self.__int_repr + '>' + str(element) + '</' + self.__int_repr + '>\n'
        if isinstance(element, str):
            self.xml_result += indent + '\t<' + self.__str_repr + '>' + str(element) + '</' + self.__str_repr + '>\n'
        elif type(element) in [type(list()), type(tuple()), type(dict())]:
            for el in element:
                self.__recurse2(el, indent + '\t')
        else:
            try: # Attribute names are printed only here
                attrs = vars(element)
                self.xml_result += indent + '<' + element.__class__.__name__ + '>\n'
                for attr in attrs:
                    self.xml_result += indent + '\t'  + '<'+ attr +'>\n'
                    self.__recurse2(attrs[attr], indent + '\t')
                    self.xml_result += indent + '\t'  + '</'+ attr +'>\n'
                self.xml_result += indent + '</' + element.__class__.__name__ + '>\n'
            except Exception as ex:
                pass

这里是测试Class(文件的全部内容)

import unittest
from string_and_regex.xml_stuff import XmlSerializer


class Person:
    def __init__(self):
        self.name = "Sam"
        self.age = 26


class Group:
    def __init__(self):
        self.name = 'sample object'
        self.people = [Person(), Person()]


group_serialized = '<Group>\n' \
                   '\t<name>\n' \
                   '\t\t<str>sample object</str>\n' \
                   '\t</name>\n' \
                   '\t<people>\n' \
                   '\t\t<Person>\n' \
                   '\t\t\t<name>\n' \
                   '\t\t\t\t<str>Sam</str>\n' \
                   '\t\t\t</name>\n' \
                   '\t\t\t<age>\n' \
                   '\t\t\t\t<int>26</int>\n' \
                   '\t\t\t</age>\n' \
                   '\t\t</Person>\n' \
                   '\t\t<Person>\n' \
                   '\t\t\t<name>\n' \
                   '\t\t\t\t<str>Sam</str>\n' \
                   '\t\t\t</name>\n' \
                   '\t\t\t<age>\n' \
                   '\t\t\t\t<int>26</int>\n' \
                   '\t\t\t</age>\n' \
                   '\t\t</Person>\n' \
                   '\t</people>\n' \
                    "</Group>\n"


class TestXmlSerializer(unittest.TestCase):
    def test_serialize(self):
        serializer = XmlSerializer()
        xml_result = serializer.serialize(Group())
        self.assertEquals(group_serialized, xml_result)


if __name__ == '__main__':
    unittest.main()

(还见谅我自己想出来的测试用例,我知道了)

字典没有可预测的迭代顺序。当您遍历 vars(element):

attrs = vars(element)
self.xml_result += indent + '<' + element.__class__.__name__ + '>\n'
for attr in attrs:

您的每个 运行 测试都将以其自己的任意顺序迭代。这可能是相当一致的,或者是随机的,或者它可能以几乎任何方式表现,这取决于解释器实现和设置的细节。您可能在 Python 3,其中字符串哈希码是随机的。

不依赖于字典迭代顺序。