Python 当结果相等时 unittest assertEqual 失败(Python v3.6)
Python unittest assertEqual failure when results are equal (Python v3.6)
因此,由于测试声称 assertEqual
语句失败,我遇到了 unittest
结果失败的问题。
错误代码:
AssertionError: {1: ((51, 98), (31, 4)), 2: ((51, 98), (49, 80)), 3: ((31, 4), (49, 80))} != {1: ((51, 98), (31, 4)), 2: ((51, 98), (49, 80)), 3: ((31, 4), (49, 80))}
下面是单元测试代码:
class InstanceTestCase(unittest.TestCase):
def setUp(self):
self.prob = Generate.populated_instance(3, 12345678)
node_one = Node(51, 98)
node_two = Node(31, 4)
node_three = Node(49, 80)
edge_one = Edge(node_one, node_two)
edge_two = Edge(node_one, node_three)
edge_three = Edge(node_two, node_three)
self.comparison_edges = {1: edge_one, 2: edge_two, 3: edge_three}
def test_Instance(self):
self.assertEqual(self.prob.edges, self.compare_edges_dict) # returning an error
正在测试这些 classes:
class Node:
"""Represents the nodes as points with a position x, y."""
def __init__(self, x=0, y=0):
"""Create a new node at x, y."""
self.x = x
self.y = y
def __str__(self):
return "({0}, {1})".format(self.x, self.y)
def __repr__(self):
return str(self)
def __eq__(self, other):
if type(self) == type(other):
return self.x == other.x and self.y == other.y
else:
raise TypeError
def __hash__(self):
return hash((self.x, self.y))
class Edge:
"""Represents the edges as having a length and being bounded by two points."""
def __init__(self, node_one, node_two):
"""Create an edge using two nodes."""
self.node_one = node_one
self.node_two = node_two
def __str__(self):
return "({0}, {1})".format(self.node_one, self.node_two)
def __repr__(self):
return str(self)
class Instance:
count = 0
def __init__(self, node_count=0, seed=0, nodes=None, edges=None, solution_path=None, solve_time=0):
"""Create a new problem with x number of nodes.
Leave seed blank for random seed, otherwise put an eight digit number to use for the seed."""
self.node_count = node_count
self.seed = seed
self.nodes = nodes
self.edges = edges
self.solution_path = solution_path
self.solve_time = solve_time
Instance.count += 1
# makes outputs from print easier to read
def __str__(self):
return "ID: {0}\n" \
"Node count: {1}\n" \
"Seed: {2}\n" \
"Nodes: {3}\n" \
"Edges: {4}\n" \
"Solve time: {5}".format(self.problem_id,
self.node_count,
self.seed,
self.nodes,
self.edges,
self.solve_time)
def __repr__(self):
return str(self)
在测试代码中创建的 prob
对象是 Instance
class 的实例,其中包含两个字典(在方法调用之后),一个用于节点,一个用于边缘。使用 Generate
class 的 populated_instance
方法生成节点,并通过 populated_instance
方法中的不同方法调用从节点生成边。
prob.edges 字典如下所示:
{1: ((51, 98), (31, 4)), 2: ((51, 98), (49, 80)), 3: ((31, 4), (49, 80))}
并且由包含在 Edge
class 实例中的 Node
class 实例组成。正如您在上面的单元测试代码中看到的,我使用具有相同值的相同对象创建了一个等效字典。
所以,我确定 prob.edges
字典和 comparison_edges
字典是相同的,完全由正确实例化的 class 对象组成,而我不是将这些对象中的任何一个与看起来像对象的字符串进行比较。
我发现了这个关于类似问题的问题:
...但是它没有说明我的问题。
大约一个小时后,我终于意识到发生了什么,这是一个完全不同的问题。所以我要 post 我的问题和答案。
我的答案是我没有在 Edge
class.
中实现 __eq__()
方法
此方法将由其他一些方法自动调用,如果您的 class 中未实现此方法,则需要进行相等性检查的方法可能无法正常运行。
我的Edge
class原来是这样的:
class Edge:
"""Represents the edges as having a length and being bounded by two points."""
def __init__(self, node_one, node_two):
"""Create an edge using two nodes."""
self.node_one = node_one
self.node_two = node_two
def __str__(self):
return "({0}, {1})".format(self.node_one, self.node_two)
def __repr__(self):
return str(self)
包括这个之后...
def __eq__(self, other):
if type(self) == type(other):
return self.node_one == other.node_one and self.node_two == other.node_two
else:
raise TypeError
assertEqual
中使用的相等性检查工作正常。
(注意:我已经在我的 Node
class 中实现了一个覆盖的 __eq__()
方法,并且测试证实删除它也破坏了上述检查。)
从 python 文档 (https://docs.python.org/2/library/unittest.html) 看这个:
assertEqual(first, second, msg=None)
Test that first and second are
equal. If the values do not compare equal, the test will fail.
In addition, if first and second are the exact same type and one of
list, tuple, dict, set, frozenset or unicode or any type that a
subclass registers with addTypeEqualityFunc()
the type-specific
equality function will be called in order to generate a more useful
default error message (see also the list of type-specific methods).
Changed in version 2.7: Added the automatic calling of type-specific
equality function.
在我看来,'the type-specific equality function' 正在自定义 class 上调用,因此,如果自定义 __eq__()
方法不存在,则检查将失败。
有关详细信息,请参阅下面@Humbalan 的回答:)
没有自己的 __eq__()
方法 Python 只比较对象的 ID,它们当然不相等。如果你想测试不同对象的属性是否相等,你需要 __eq__()
方法。实际上,您可以根据需要在这种方法中进行比较。我有一个例子,其中相等被定义为五个属性中的两个相等。其余三个属性没有考虑。
顺便说一句:在您的 __eq__()
方法中,您还应该检查对象类型的相等性。想象一下不同 类 的两个实例,它们随机具有相同的属性 ...
因此,由于测试声称 assertEqual
语句失败,我遇到了 unittest
结果失败的问题。
错误代码:
AssertionError: {1: ((51, 98), (31, 4)), 2: ((51, 98), (49, 80)), 3: ((31, 4), (49, 80))} != {1: ((51, 98), (31, 4)), 2: ((51, 98), (49, 80)), 3: ((31, 4), (49, 80))}
下面是单元测试代码:
class InstanceTestCase(unittest.TestCase):
def setUp(self):
self.prob = Generate.populated_instance(3, 12345678)
node_one = Node(51, 98)
node_two = Node(31, 4)
node_three = Node(49, 80)
edge_one = Edge(node_one, node_two)
edge_two = Edge(node_one, node_three)
edge_three = Edge(node_two, node_three)
self.comparison_edges = {1: edge_one, 2: edge_two, 3: edge_three}
def test_Instance(self):
self.assertEqual(self.prob.edges, self.compare_edges_dict) # returning an error
正在测试这些 classes:
class Node:
"""Represents the nodes as points with a position x, y."""
def __init__(self, x=0, y=0):
"""Create a new node at x, y."""
self.x = x
self.y = y
def __str__(self):
return "({0}, {1})".format(self.x, self.y)
def __repr__(self):
return str(self)
def __eq__(self, other):
if type(self) == type(other):
return self.x == other.x and self.y == other.y
else:
raise TypeError
def __hash__(self):
return hash((self.x, self.y))
class Edge:
"""Represents the edges as having a length and being bounded by two points."""
def __init__(self, node_one, node_two):
"""Create an edge using two nodes."""
self.node_one = node_one
self.node_two = node_two
def __str__(self):
return "({0}, {1})".format(self.node_one, self.node_two)
def __repr__(self):
return str(self)
class Instance:
count = 0
def __init__(self, node_count=0, seed=0, nodes=None, edges=None, solution_path=None, solve_time=0):
"""Create a new problem with x number of nodes.
Leave seed blank for random seed, otherwise put an eight digit number to use for the seed."""
self.node_count = node_count
self.seed = seed
self.nodes = nodes
self.edges = edges
self.solution_path = solution_path
self.solve_time = solve_time
Instance.count += 1
# makes outputs from print easier to read
def __str__(self):
return "ID: {0}\n" \
"Node count: {1}\n" \
"Seed: {2}\n" \
"Nodes: {3}\n" \
"Edges: {4}\n" \
"Solve time: {5}".format(self.problem_id,
self.node_count,
self.seed,
self.nodes,
self.edges,
self.solve_time)
def __repr__(self):
return str(self)
在测试代码中创建的 prob
对象是 Instance
class 的实例,其中包含两个字典(在方法调用之后),一个用于节点,一个用于边缘。使用 Generate
class 的 populated_instance
方法生成节点,并通过 populated_instance
方法中的不同方法调用从节点生成边。
prob.edges 字典如下所示:
{1: ((51, 98), (31, 4)), 2: ((51, 98), (49, 80)), 3: ((31, 4), (49, 80))}
并且由包含在 Edge
class 实例中的 Node
class 实例组成。正如您在上面的单元测试代码中看到的,我使用具有相同值的相同对象创建了一个等效字典。
所以,我确定 prob.edges
字典和 comparison_edges
字典是相同的,完全由正确实例化的 class 对象组成,而我不是将这些对象中的任何一个与看起来像对象的字符串进行比较。
我发现了这个关于类似问题的问题:
大约一个小时后,我终于意识到发生了什么,这是一个完全不同的问题。所以我要 post 我的问题和答案。
我的答案是我没有在 Edge
class.
__eq__()
方法
此方法将由其他一些方法自动调用,如果您的 class 中未实现此方法,则需要进行相等性检查的方法可能无法正常运行。
我的Edge
class原来是这样的:
class Edge:
"""Represents the edges as having a length and being bounded by two points."""
def __init__(self, node_one, node_two):
"""Create an edge using two nodes."""
self.node_one = node_one
self.node_two = node_two
def __str__(self):
return "({0}, {1})".format(self.node_one, self.node_two)
def __repr__(self):
return str(self)
包括这个之后...
def __eq__(self, other):
if type(self) == type(other):
return self.node_one == other.node_one and self.node_two == other.node_two
else:
raise TypeError
assertEqual
中使用的相等性检查工作正常。
(注意:我已经在我的 Node
class 中实现了一个覆盖的 __eq__()
方法,并且测试证实删除它也破坏了上述检查。)
从 python 文档 (https://docs.python.org/2/library/unittest.html) 看这个:
assertEqual(first, second, msg=None)
Test that first and second are equal. If the values do not compare equal, the test will fail.In addition, if first and second are the exact same type and one of list, tuple, dict, set, frozenset or unicode or any type that a subclass registers with
addTypeEqualityFunc()
the type-specific equality function will be called in order to generate a more useful default error message (see also the list of type-specific methods).Changed in version 2.7: Added the automatic calling of type-specific equality function.
在我看来,'the type-specific equality function' 正在自定义 class 上调用,因此,如果自定义 __eq__()
方法不存在,则检查将失败。
有关详细信息,请参阅下面@Humbalan 的回答:)
没有自己的 __eq__()
方法 Python 只比较对象的 ID,它们当然不相等。如果你想测试不同对象的属性是否相等,你需要 __eq__()
方法。实际上,您可以根据需要在这种方法中进行比较。我有一个例子,其中相等被定义为五个属性中的两个相等。其余三个属性没有考虑。
顺便说一句:在您的 __eq__()
方法中,您还应该检查对象类型的相等性。想象一下不同 类 的两个实例,它们随机具有相同的属性 ...