우리 개발팀은 최대 80 자 길이의 PEP8 린터를 사용합니다 .
파이썬으로 단위 테스트를 작성할 때 각 테스트가 수행하는 작업을 설명하는 메서드 이름 을 갖고 싶습니다 . 그러나 이것은 종종 글자 수 제한을 초과하게 만듭니다.
다음은 너무 긴 함수의 예입니다.
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) 내에서 테스트를 실행할 때 테스트 이름을 볼 수 없습니다.
-
백 슬래시 (논리적 줄 연속 문자)로 줄을 계속할 수 있습니다.
불행히도 이것은 Dan의 답변에서 언급했듯이 Python의 옵션이 아닙니다.
-
테스트를 멈출 수 있습니다.
이것은 어떤면에서 의미가 있지만 잘 형식화 된 테스트 스위트를 장려하는 것이 좋습니다.
-
줄 길이 제한을 늘릴 수 있습니다.
우리 팀은 좁은 디스플레이에서 코드를 읽을 수 있도록하는 데 도움이되므로 제한이있는 것을 좋아하므로 이것이 최선의 선택 이 아닙니다 .
-
test
메서드의 시작 부분에서 제거 할 수 있습니다.이것은 옵션이 아닙니다. Python의 테스트 실행기는 시작하기 위해 모든 테스트 메서드가 필요
test
합니다. 그렇지 않으면 선택하지 않습니다.편집 : 일부 테스트 실행기에서는 테스트 함수를 검색 할 때 정규식을 지정할 수 있지만 프로젝트에서 작업하는 모든 사람을위한 추가 설정이므로이 작업을 수행하지 않을 것입니다.
-
EventListener를 자체 클래스로 분리하고 별도로 테스트 할 수 있습니다.
이벤트 리스너 는 자체 클래스에 있으며 테스트되었습니다. ClientConnection 내에서 발생하는 이벤트에 의해 트리거되는 인터페이스입니다. 이런 종류의 제안은 좋은 의도를 가지고있는 것 같지만 잘못된 방향으로 원래 질문에 답하는 데 도움이되지 않습니다.
-
Behave 와 같은 BDD 프레임 워크를 사용할 수 있습니다 . 표현 테스트를 위해 설계되었습니다.
이것은 사실이며 앞으로 더 많이 사용하고 싶습니다. 함수 이름을 여러 줄로 나누는 방법을 여전히 알고 싶습니다.
궁극적으로 …
파이썬에서 긴 함수 선언을 여러 줄로 분할 하는 방법이 있습니까?
예를 들면 …
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()
아니면 총알을 깨물고 직접 줄여야할까요?
답변
답변
당신은 수 또한 변이 실내 장식 쓰기 .__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()
파이썬이 소스에 인접한 문자열 리터럴을 연결한다는 사실에 의존합니다.
답변
이 질문에 대한 답변 : 특정 파일에서 pep8 오류를 비활성화하는 방법은 무엇입니까? , # nopep8
또는 # noqa
후행 주석을 사용하여 긴 줄에 대해 PEP-8을 비활성화합니다. 규칙을 어길 때 아는 것이 중요합니다. 물론, Zen of Python은 “특수한 경우는 규칙을 위반할만큼 특별하지 않습니다.”라고 말합니다.
답변
에서 메소드 이름을 가져 오므 로 메소드 대신 클래스에 데코레이터 를 적용 할 수 있습니다 .unittest
dir(class)
데코레이터 decorate_method
는 클래스 메소드를 거치고 func_mapping
사전에 따라 메소드의 이름을 바꿉니다 .
@Sean Vieira의 데코레이터 답변을 본 후 생각했습니다.
import unittest, inspect
# dictionary map short to long function names
func_mapping = {}
func_mapping['test_client'] = ("test_that_client_event_listener_receives_"
"connection_refused_error_without_server")
# continue added more funtion name mapping to the dict
def decorate_method(func_map, prefix='test_'):
def decorate_class(cls):
for (name, m) in inspect.getmembers(cls, inspect.ismethod):
if name in func_map and name.startswith(prefix):
setattr(cls, func_map.get(name), m) # set func name with new name from mapping dict
delattr(cls, name) # delete the original short name class attribute
return cls
return decorate_class
@decorate_method(func_mapping)
class ClientConnectionTest(unittest.TestCase):
def test_client(self):
# dummy print for testing
print('i am test_client')
# self.given_server_is_offline()
# self.given_client_connection()
# self.when_client_connection_starts()
# self.then_client_receives_connection_refused_error()
unittest
아래와 같이 테스트 실행 은 전체 긴 설명 함수 이름을 보여 주며 구현에서 그렇게 우아하고 읽을 수는 없지만 귀하의 경우에 작동한다고 생각합니다.
>>> unittest.main(verbosity=2)
test_that_client_event_listener_receives_connection_refused_error_without_server (__main__.ClientConnectionTest) ... i am client_test
ok
답변
문제에 대한 상황 별 접근 방식입니다. 제시 한 테스트 케이스는 실제로 테스트 케이스가 수행하는 데 필요한 단계를 설명 하는 자연어 형식 과 매우 유사합니다 .
여기 에서 behave
Behavior Driver 개발 스타일 프레임 워크를 사용하는 것이 더 합리적인지 확인하십시오. 귀하의 “기능”합니다 (방법을 볼처럼 보일 수 있습니다 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
패키지 , 샘플 사용도 있습니다.
답변
이런 종류의 이름에 대한 필요성은 다른 냄새를 암시 할 수 있습니다.
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):
...
“테스트”는 암시 적이므로 이름에 유용하지 않습니다.
제게 주신 모든 코드를 사용하여 마지막 조언은 테스트 코드를 리팩토링 한 다음 문제를 재검토하는 것입니다 (아직 문제가있는 경우).
답변
더 짧은 함수 이름 솔루션은 많은 장점이 있습니다. 실제 함수 이름에 실제로 필요한 것과 이미 제공된 것이 무엇인지 생각해보십시오 .
test_that_client_event_listener_receives_connection_refused_error_without_server(self):
확실히 당신은 그것을 실행할 때 그것이 테스트라는 것을 이미 알고 있습니까? 정말로 밑줄을 사용해야합니까? 이름을 이해하려면 ‘that’과 같은 단어가 정말 필요한가요? 낙타 케이스는 읽을 수있는 것처럼 보입니까? 위의 재 작성으로 아래의 첫 번째 예는 어떻습니까 (문자 수 = 79) : 작은 공통 단어 모음에 대해 약어를 사용하는 규칙을 수락하는 것이 훨씬 더 효과적입니다 (예 : Connection = Conn, Error = Err). 약어를 사용할 때는 문맥을 염두에두고 혼동 가능성이 없을 때만 사용하십시오. 아래 두 번째 예입니다. 정보가 클래스 이름에 있으므로 메서드 이름에서 테스트 대상으로 클라이언트를 실제로 언급 할 필요가 없다는 사실을 수락하면 세 번째 예제가 적절할 수 있습니다. (54) 문자.
ClientEventListenerReceivesConnectionRefusedErrorWithoutServer (self) :
ClientEventListenerReceivesConnRefusedErrWithoutServer (self) :
EventListenerReceiveConnRefusedErrWithoutServer (self) :
또한 B Rad C의 제안에 동의합니다. “self.assert의 msg kwarg arg에 설명적인 이름을 사용하십시오.”테스트 스위트가 실행될 때 실패한 테스트의 출력 만 보는 데 관심이 있어야합니다. 필요한 모든 테스트를 작성했는지 확인하는 것은 메서드 이름이 너무 자세하다는 것에 의존해서는 안됩니다.
추신 : 아마도 불필요한 ‘WithoutServer’도 제거 할 것입니다. 어떤 이유로 든 서버에 연결할 수없는 경우 클라이언트 이벤트 처리기가 이벤트를 수신하지 않아야합니까? (tbh 클라이언트가 서버에 연결할 수 없다면 일종의 ‘연결 불가’를 수신하는 것이 더 나을 것이라고 생각하지만 연결 거부는 서버를 찾을 수 있지만 연결 자체를 거부한다는 것을 나타냅니다.)