我们的开发团队使用PEP8 linter,需要最大行长度为80个字符。
当我在python中编写单元测试时,我喜欢使用描述性方法名称来描述每个测试的作用。然而,这通常会导致我超出角色限制。
以下是一个太长的函数示例......
class ClientConnectionTest(unittest.TestCase):
def test_that_client_event_listener_receives_connection_refused_error_without_server(self):
self.given_server_is_offline()
self.given_client_connection()
self.when_client_connection_starts()
self.then_client_receives_connection_refused_error()
你可以写更短的方法名称!
我知道,但我不想失去测试名称的描述性。
您可以在每个测试之上编写多行注释,而不是使用长名称!
这是一个不错的主意,但是当我在IDE(PyCharm)中运行测试时,我将无法看到测试名称。
也许你可以用反斜杠(逻辑行继续符)继续行。
不幸的是,这不是Python中的一个选项,正如Dan的回答中提到的那样。
你可以停止测试。
这在某些方面是有道理的,但鼓励格式良好的测试套件是很好的。
您可以增加行长限制。
我们的团队喜欢有限制,因为它有助于在窄显示屏上保持代码可读,因此这不是最佳选项。
您可以从方法的开头删除
test
。
这不是一个选择。 Python的测试运行器需要所有测试方法都以test
开头,否则它将无法接收它们。
编辑:一些测试运行器允许您在搜索测试函数时指定正则表达式,但我不想这样做,因为它是为项目所有人工作的额外设置。此外,它并没有真正回答原来的问题。
您可以将EventListener分隔到自己的类中并单独测试它。
事件监听器 在其自己的类中(并经过测试)。它只是一个由ClientConnection中发生的事件触发的接口。这种建议似乎有很好的意图,但是被误导了,并没有帮助回答原来的问题。
您可以使用像Behave这样的BDD框架。它专为表达测试而设计。
这是事实,我希望将来可以使用更多这些。虽然我仍然想知道如何跨行分割函数名称。
Python中是否有办法跨多行分割长函数声明?
例如......
def test_that_client_event_listener_receives_
connection_refused_error_without_server(self):
self.given_server_is_offline()
self.given_client_connection()
self.when_client_connection_starts()
self.then_client_receives_connection_refused_error()
或者我必须咬紧牙关并自己缩短它?
答案 0 :(得分:74)
不,这是不可能的。
在大多数情况下,从功能的可读性和可用性的角度来看,这样一个长名称是不可取的,尽管您的测试名称用例看起来很合理。
lexical rules of Python不允许将单个标记(在本例中为标识符)分割为多行。逻辑行继续符(行尾的\
)可以将多个物理行连接到一个逻辑行,但不能跨多行连接单个令牌。
答案 1 :(得分:50)
你还可以编写一个装饰器,为方法改变.__name__
。
def test_name(name):
def wrapper(f):
f.__name__ = name
return f
return wrapper
然后你可以写:
class ClientConnectionTest(unittest.TestCase):
@test_name("test_that_client_event_listener_"
"receives_connection_refused_error_without_server")
def test_client_offline_behavior(self):
self.given_server_is_offline()
self.given_client_connection()
self.when_client_connection_starts()
self.then_client_receives_connection_refused_error()
依赖于Python连接源相邻字符串文字的事实。
答案 2 :(得分:33)
根据这个问题的答案:How to disable a pep8 error in a specific file?,使用# nopep8
或# noqa
结尾注释来禁用长线PEP-8。知道什么时候打破规则很重要。当然,Python的Zen会告诉你“特殊情况不足以破坏规则。”
答案 3 :(得分:7)
针对问题的特定于上下文的方法的排序。您提供的测试用例实际上看起来非常像自然语言格式,用于描述测试用例的必要步骤。
在这里查看使用behave
Behavior Driver development style framework是否更有意义。您的“功能”可能如下(请参阅given
,when
,then
如何反映您的内容:
Feature: Connect error testing
Scenario: Client event listener receives connection refused error without server
Given server is offline
when client connect starts
then client receives connection refused error
还有相关主题的最新答案中的相关pyspecs
package示例用法:
答案 4 :(得分:5)
较短的功能名称解决方案有很多优点。想想你的实际功能名称中已经真正的内容以及已经提供的内容。
test_that_client_event_listener_receives_connection_refused_error_without_server(self):
当你运行它时,你肯定知道它是一个测试吗?你真的需要使用下划线吗?是像“'”这样的词。真的需要理解这个名字吗?骆驼的情况会如同可读吗?下面的第一个例子如何重写上面的内容(字符数= 79): 接受使用缩写来获得一小部分常用词的惯例甚至更有效,例如: Connection = Conn,Error = Err。使用缩写时,您必须注意上下文,只有在不存在混淆时才使用它们 - 下面的第二个例子。 如果您接受实际上不需要在方法名称中提及客户端作为测试主题,因为该信息在类名中,那么第三个示例可能是合适的。 (54)字符。
ClientEventListenerReceivesConnectionRefusedErrorWithoutServer(个体):
ClientEventListenerReceivesConnRefusedErrWithoutServer(个体):
EventListenerReceiveConnRefusedErrWithoutServer(个体):
我也同意B Rad C&#34的建议;使用描述性名称作为msg kwarg arg in self.assert"您应该只对运行测试套件时失败测试的输出感兴趣。验证您已完成所有必要的测试不应该依赖于方法名称如此详细。
P.S。我可能也会删除“没有服务器”#39;也是多余的。如果服务器因任何原因无法联系,客户端事件处理程序是否应该接收事件? (虽然我认为如果客户端无法连接到服务器会收到某种“连接不可用”的情况会更好,但拒绝连接表明服务器可以是发现但拒绝连接本身。)
答案 5 :(得分:5)
对这种名字的需求可能暗示其他气味。
class ClientConnectionTest(unittest.TestCase):
def test_that_client_event_listener_receives_connection_refused_error_without_server(self):
...
ClientConnectionTest
听起来相当广泛(并且根本不像一个可测试的单位),并且很可能是一个大型课程,里面有大量的测试可以重新聚焦。像这样:
class ClientEventListenerTest(unittest.TestCase):
def receives_connection_refused_without_server(self):
...
“测试”在名称中没用,因为它暗示着。
根据您提供的所有代码,我的最终建议是:重构您的测试代码,然后重新审视您的问题(如果它仍在那里)。