테스트를 위해 내부 / 공개를 개인용으로 만들거나 PrivateObject와 같은 일종의 핵을 사용 하시겠습니까?


26

저는 코드 테스트의 초보자이며 assert창녀 였습니다 . 단위 테스트에서 나를 걱정하는 한 가지는 종종 그렇지 않은 필드 를 만들 public거나 (또는 ​​적어도 internal) 필드를 작성하고 대신 메소드 를 만드는 것입니다 .privatereadonlyprivateprotected virtual

최근에 PrivateObject 클래스 와 같은 것을 사용하여 리플렉션을 통해 객체의 모든 항목에 액세스 하여이를 피할 수 있음을 발견했습니다 . 그러나 이렇게하면 테스트를 유지 관리하기가 어렵습니다 (컴파일 시간보다는 실행시 실패합니다. 간단한 이름 바꾸기로 인해 깨지기 때문에 디버그하기가 어렵습니다 ...). 이것에 대한 당신의 의견은 무엇입니까? 액세스 제한에 관한 단위 테스트의 모범 사례는 무엇입니까?

편집 : 예를 들어 디스크의 파일에 캐시가있는 클래스가 있고 테스트에서 메모리에 쓰려고한다고 생각하십시오.


2
파이썬 사람들은 공개적입니다. 그들은 행복합니다. 왜 걱정? 왜 모든 것을 공개하지 않습니까?
S.Lott

12
왜냐하면 대부분의 최상위 언어에서 모범 사례와는 거리가 멀기 때문입니다. 진정한 대답은 좋은 인터페이스를 사용하는 것이므로 모의 객체를 사용하여 테스트를 수행 할 수 있습니다.
Rig

2
@Rig : 파이썬은 최고의 언어가 아닙니까? 흥미 롭군
S.Lott

7
"대부분의 최상위 언어에서 모범 사례와는 거리가 멀다"는 "Python은 최상위 언어가 아닙니다"라는 논리적 의미를 갖지 않습니다.
Mike Nakis

1
정확하게는 최상위 언어이지만 대부분의 최상위 언어는 Python이 아니며 적절한 범위 설정을 보증합니다. 나는 나의 진술을지지한다. 변수의 범위를 유지하면서 고도로 테스트 가능한 소프트웨어를 만들도록 설계된 패턴이 있습니다. 파이썬 프로그래머조차도 내가 본 것의 접두사로 범위를 모방하는 경향이 있습니다.
Rig

답변:


36

절대로

확인 public(또는 이상 internal)했을 필드 private되지 않는다는 것은, 그렇지 않으면 readonly그들을, 메이크업의 private방법 protected virtual대신에

특히 필드를 읽기 전용이 아닌 경우 변경할 수없는 객체를 변경할 수 있으며 이는 재앙이됩니다.

테스트는 객체를 블랙 박스 ( Wikipedia ) 로 간주해야합니다 . 즉, 구현의 세부 사항이 아니라 객체의 공용 인터페이스에만 관심이 있어야합니다.

공용 인터페이스를 사용하여 개체를 충분히 테스트 할 수없는 경우 테스트를 용이하게하는 공식적이고 유용한 확장 기능을 인터페이스에 제공하는 방법을 찾아야합니다. 예를 들어, 한 쌍의 등록 / 등록 취소 메소드 만있는 등록 시스템은 현재 적용 할 필요가없는 경우에도 IsRegistered 메소드를 활용할 수 있습니다. 여전히 인터페이스에 대한 공식적이고 유용한 확장이며 테스트를 수용 할 수 있습니다.

중요한 것은 객체의 구현을 변경하면 단위 테스트를 변경할 필요가 없다는 것입니다. 이론적으로 단위 테스트를 한 번 작성한 다음 여러 프로그래머에게 단위 테스트를 수행하기 위해 테스트 할 객체의 완전히 다른 여러 구현을 코딩하도록 요청할 수 있어야합니다.


2
정확하게! 리플렉션이나 해킹없이 단위 테스트를 할 수 없다면 API 또는 디자인에 실수가있을 수 있습니다.
팔콘

테스트에서 조롱하는 데 도움이되는 private방법 protected virtual을 만드는 것이 나쁜 실천으로 간주 된다고 말하고 있습니까?
Robula

1
@Robula 내 책에서 그렇습니다. 비공개 멤버에 액세스 할 수 없기 때문에 프로덕션 코드와 동일한 패키지로 테스트를 작성하지도 않습니다. 모의도 사용하지 않습니다. 물론 모의를 사용해야하는 경우 모의를 용이하게하기 위해 필요한 모든 조치를 취해야하므로 보호 된 가상은 많은 상황에서 실질적인 타협이 될 수 있습니다. 그러나 이상적으로는 디자인에 모의가 필요없고 대체 구현 만 필요하며 이상적으로 테스트는 화이트 박스 테스트가 아닌 블랙 박스 테스트이므로 모의없이 모의 테스트가 이루어집니다.
마이크 나 키스

13

C #에서는 InternalsVisibleToAttribute테스트 어셈블리를 사용하여 테스트중인 어셈블리의 internal클래스 를 볼 수 있습니다 . 이미 알고있는 것 같습니다.

대부분의 경우 어셈블리의 공개 API 테스트에만 관심이 있습니다. 일부 단위의 화이트 박스 테스트를 수행하려는 경우 코드를 internal클래스 로 이동하여 public해당 클래스 의 메소드로 만듭니다 . 그런 다음 해당 클래스에 대한 단위 테스트를 코딩 할 수 있습니다.

이것은 의존성 주입과 전략 패턴에 적합합니다. 메소드를 인터페이스로 추상화하고 인터페이스를 상위 오브젝트의 생성자에 삽입하고 상위가 적절하게 위임되는지 테스트 할 수 있습니다. 그런 다음 자식 개체가 올바르게 동작하는지 테스트 할 수 있습니다. 이것은 모든 것을 더 모듈화합니다.


8

내 경험상 특별히 테스트를 위해 클래스의 내부를 노출시키지 않는 것이 가장 좋습니다. 비록 이것이 테스트를보다 쉽게 ​​작성하는 것처럼 보일 수 있습니다. 테스트는 수업의 첫 번째 클라이언트이므로 공용 인터페이스를 통해 수업을 테스트하기 어려운 경우 다른 장소에서도 수업을 사용하기가 어려울 수 있습니다.

퍼블릭 API를 통해 클래스를 테스트하는 것이 얼마나 쉬운지는 클래스 사용이 얼마나 쉬운 지에 대한 피드백입니다. 클래스 사용법을 프로토 타입으로 만드는 방법으로 테스트를 부분적으로 생각하십시오.

테스트에서 공개 API를 통해 사용할 수없는 클래스에 대해 무언가를 감지해야하는 이유를 고려하십시오. 아마도 당신의 수업이 너무 많은 일을하고 대신에 협력 수업 그룹으로 분해되어야합니까? 그런 다음 일부 협업 클래스를 조롱하여 테스트중인 클래스가 수행중인 작업을 감지 할 수 있습니다.

종속성 반전 원칙 을 적용하고 클래스 사이에 인터페이스를 도입하여 테스트에서 조롱 할 수 있습니다. 제어 역전을 사용하여 공동 작업자에게 테스트를 제공 할 수 있습니다 .

또한 올바른 정보가 노출되고 나머지는 숨겨지는 강력하고 느슨하게 결합 된 방식으로 클래스 인터페이스를 구성하는 데 도움이되도록 " tell't ask" 원칙을 적용하는 것이 좋습니다.


6

개인적으로 나는 테스트 할 수있는 한 순수한 코드를 선호하고 테스트 코드에 해킹이 필요한 경우 (그리고 C ++ 불쾌한 포인터 등) 기꺼이 그렇게합니다.



1
동의합니다. 이것이 방법입니다. 테스트 코드에 추함을 유지하면 아무것도 해칠 수 없습니다.
Alan Delimon

@AlanDelimon 후속 유지 보수 프로그래머의 마음을 아프게하지 않을 수 있습니까?
flamingpenguin

1
@flamingpenguin 못생긴 코드는 어디에서나 프로그래머를 해칠 수 있습니다. 그러나 추악한 테스트 코드는 클래스를 수정하는 사람들에게만 영향을 미치며 단순히 코드를 소비하는 사람들에게는 영향을 미치지 않기 때문에 덜 해를 끼칠 것입니다.
Dan Neely

2
@flamingpenguin 어쩌면 못생긴 코드를 어딘가에 배치 해야하는 경우 수정이 필요없고 응용 프로그램의 일부가 될 가능성이 적은 단위 테스트 일 수도 있습니다.
Alan Delimon

5

코드의 가시성은 단위 테스트와 아무 관련이 없습니다!

테스트에서 숨길 목적으로 메소드를 비공개로 만들고 테스트를 위해 공개하도록 공개하지 않습니까? 이것은 테스트가 아닌 여기에서 필수적인 구현입니다. 코드는 서버이지만 코드 는 아닙니다 .

숨겨진 (비공개 또는 내부) 메소드 및 속성에 액세스 할 수있는 방법은 많이 있습니다. 많은 테스트 프레임 워크 및 IDE (예 : Visual Studio)는 액세스에 필요한 모든 것을 생성하여 여기에서 지원하므로 테스트 사례 만 작성하면됩니다. 왜 걱정? 코드를 깨끗하고 깔끔하게 유지하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.