때때로 개인 기능은 아직 추출되지 않은 내부 기능 단위입니다. 그렇다면 왜 테스트하지 않습니까?


9

때로는 모듈이나 클래스의 개인 함수가 아직 추출되지 않은 내부 기능 단위이므로 자체 테스트가 필요할 수 있습니다. 그렇다면 왜 테스트하지 않습니까? 우리는 것이다 그들이 추출 할 때 경우 / 나중에 그들을 위해 테스트를 작성. 그렇다면 여전히 동일한 파일의 일부인 테스트를 작성하지 않겠습니까?

시연하려면 :

여기에 이미지 설명을 입력하십시오

먼저 나는 썼다 module_a. 이제 테스트를 작성하고 싶습니다. 'private'기능을 테스트하고 싶습니다 _private_func. 나중에 테스트를 작성하지 않는 이유를 이해하지 못합니다. 나중에 나중에 자체 내부 모듈로 리팩터링 한 다음 테스트를 작성할 수 있습니다.


다음 기능을 가진 모듈이 있다고 가정하십시오 (클래스 일 수도 있음).

def public_func(a):
    b = _do_stuff(a)
    return _do_more_stuff(b)

_do_stuff_do_more_stuff모듈의 '개인'기능은 다음과 같습니다.

구현 세부 정보가 아니라 공용 인터페이스 만 테스트해야한다는 생각을 이해합니다. 그러나 여기에 있습니다 :

_do_stuff_do_more_stuff모듈의 기능의 대부분을 포함하고있다. 그들 각각은 다른 '내부'모듈의 공용 기능 일 수 있습니다. 그러나 그것들은 아직 진화되지 않았고 파일을 분리하기 위해 추출 될만큼 충분히 크지 않았습니다.

따라서 이러한 기능을 테스트하는 것은 기능의 중요한 단위이기 때문에 적절합니다. 그것들이 공공 기능과 다른 모듈에 있다면, 우리는 그것들을 테스트했을 것입니다. 그렇다면 아직 다른 파일로 추출되지 않았을 때 테스트하지 않는 이유는 무엇입니까?



2
"비공개 방법은 단위 테스트에 유리합니다 ..." "... 개인적인 방법을 고수 하면 단위 테스트를 유용하고 안정적으로 향상시킬 수 있습니다. 반면에"테스트 가능성 "에 대한 액세스 제한을 약화하면 이해하기 어렵고 모호합니다. 사소한 리팩토링에 의해 영구적으로 파손될 위험이있는 테스트 코드; 솔직히 기술 부채처럼 보이는 것 "
gnat

3
"개인 기능을 테스트해야합니까?" 아뇨, 절대 절대
David Arno

2
@DavidArno 왜? 내부 테스트의 대안은 무엇입니까? 통합 테스트 만? 아니면 더 많은 것을 공개합니까? (내 경험에서 나는 주로 내부 클래스에 public 메소드, 민간하지 방법을 테스트하지만)
CodesInChaos

1
테스트를 작성해야 할만큼 중요하다면 이미 별도의 모듈에 있어야합니다. 그렇지 않은 경우 공개 API를 사용하여 동작을 테스트하십시오.
Vincent Savard

답변:


14

테스트 필요성은 공개 필요성과 동일하지 않습니다.

사소한 코드는 노출에 관계없이 테스트가 필요합니다. 공개되지 않은 행동은 테스트 할 필요없이 존재할 필요는 없습니다.

이러한 상충되는 견해로 인해 모든 기능을 공개하거나 공개되지 않는 한 코드를 함수에 포함시키지 않을 수 있습니다.

이것은 답이 아닙니다. 개인 도우미 기능을 기꺼이 만드십시오. 가능한 공용 인터페이스를 사용하여 테스트하십시오.

공용 인터페이스를 통한 테스트가 개인 기능을 충분히 발휘하지 못하면 개인 기능이 많은 것을 허용하려고합니다.

유효성 검사는 개인 기능이 허용하는 범위를 좁히는 데 도움이 될 수 있습니다. 공개 인터페이스를 통해 null을 전달할 수없는 경우에도 예외가 발생해도 예외를 throw 할 수 있습니다.

왜해야합니까? 당신이 볼 수없는 것을 왜 테스트해야합니까? 상황이 변하기 때문에. 지금은 비공개이지만 나중에 공개 할 수 있습니다. 호출 코드가 변경 될 수 있습니다. 널을 명시 적으로 거부하는 코드는 올바른 사용법과 예상 상태를 명확하게합니다.

물론 null은 괜찮을 수 있습니다. 이것은 단지 예일뿐입니다. 그러나 무언가를 기대한다면, 그 기대를 분명히하는 것이 유용합니다.

그것은 당신이 염두에 두었던 테스트가 아닐 수도 있지만, 적절한 경우 개인 도우미 기능을 기꺼이 만들 수 있기를 바랍니다.

테스트하려는 욕구는 좋지만 퍼블릭 API 디자인의 원동력이되어서는 안됩니다. 사용하기 쉬운 공개 API를 설계하십시오. 모든 기능이 공개되면 아닐 것입니다. API는 사람들이 코드에 들어 가지 않고 사용하는 방법을 이해할 수있는 것이어야합니다. 그런 이상한 도우미 기능이 무엇인지 궁금해하는 사람들을 두지 마십시오.

내부 모듈에 퍼블릭 헬퍼 기능을 숨기는 것은 테스트를 위해 헬퍼를 노출시키면서 깨끗한 API의 필요성을 존중하려는 시도입니다. 나는 이것이 틀렸다고 말하지 않을 것이다. 다른 아키텍처 계층을 향한 첫 단계를 밟을 수 있습니다. 그러나 개인 도우미 기능을 먼저 사용하는 공개 기능을 통해 테스트하는 기술을 숙달하십시오. 그렇게하면이 해결 방법을 과도하게 사용하지 않습니다.


나는 접근 방식을 생각해 냈습니다. 귀하의 의견을 듣고 싶습니다 : 개인 기능을 테스트하려는 상황에 처할 때마다 공개 기능 중 하나를 통해 충분히 테스트 할 수 있는지 확인합니다 (모든 엣지 케이스 등 포함). 가능하면이 함수에 대한 테스트를 구체적으로 작성하지는 않지만이 함수를 사용하는 공용 함수를 테스트해야만 테스트 할 수 있습니다. 그러나 공용 인터페이스를 통해 기능을 충분히 테스트 할 수 없다고 생각하고 자체 테스트를 수행 해야하는 경우 공용 모듈이있는 내부 모듈로 추출하여 테스트를 작성합니다. 어떻게 생각해?
Aviv Cohn

나는 여기에 대답 한 다른 사람들과 같은 것을 묻고 있다고 말할 것입니다 :) 나는 모든 사람들의 의견을 듣고 싶습니다.
Aviv Cohn

다시 한 번 말하지 않겠습니다. 사용성에 어떤 영향을 미치는지 주시하는 것에 대해 아무 말도하지 않은 것이 걱정입니다. 공공과 민간의 차이는 구조적이지 않습니다. 사용법입니다. 공공과 민간의 차이가 정문과 뒷문 인 경우 뒤뜰에 창고를 만드는 것이 좋습니다. 좋아. 사람들이 거기서 길을 잃지 않는 한.
candied_orange

1
"공개 인터페이스를 통한 테스트가 개인 기능을 충분히 발휘하지 못하면 개인 기능이 많은 것을 허용하려고합니다."
Kris Welsh

7

짧은 답변 : 아니요

더 긴 대답 : 예, 그러나 수업의 공개 'API'를 통해

클래스의 개인 멤버에 대한 전체 아이디어는 코드의 '단위'외부에서 볼 수 없어야하는 기능을 나타내지 만 그 단위를 크게 정의하려는 경우입니다. 객체 지향 코드에서 단위는 종종 클래스가됩니다.

다양한 입력 상태 조합을 통해 모든 개인 기능을 호출 할 수 있도록 클래스를 설계해야합니다. 비교적 간단한 방법이 없다면 디자인에 더주의를 기울여야한다는 것을 암시합니다.


질문을 명확히 한 후에 이것은 의미론의 문제 일뿐입니다. 문제의 코드가 별도의 독립형 장치로 작동 할 수 있고 공용 코드 인 것처럼 테스트되는 경우 독립형 모듈로 코드를 옮기지 않으면 어떤 이점도 얻을 수 없습니다. 현재는 명백히 공개 코드가 다른 모듈에 숨겨져있는 이유에 대해 미래 개발자 (6 개월 내에 자신을 포함하여)를 혼동시키는 역할을합니다.


안녕, 답변 주셔서 감사합니다 :) 질문을 다시 읽어주십시오, 나는 명확히하기 위해 편집했습니다.
Aviv Cohn 2016

나는 접근 방식을 생각해 냈습니다. 귀하의 의견을 듣고 싶습니다 : 개인 기능을 테스트하려는 상황에 처할 때마다 공개 기능 중 하나를 통해 충분히 테스트 할 수 있는지 확인합니다 (모든 엣지 케이스 등 포함). 가능하면이 함수에 대한 테스트를 구체적으로 작성하지는 않지만이 함수를 사용하는 공용 함수를 테스트해야만 테스트 할 수 있습니다. 그러나 공용 인터페이스를 통해 기능을 충분히 테스트 할 수 없다고 생각하고 자체 테스트를 수행 해야하는 경우 공용 모듈이있는 내부 모듈로 추출하여 테스트를 작성합니다. 어떻게 생각해?
Aviv Cohn

나는 여기에 대답 한 다른 사람들과 같은 것을 묻고 있다고 말할 것입니다 :) 나는 모든 사람들의 의견을 듣고 싶습니다.
Aviv Cohn

5

개인 함수의 요점은 공용 API를 변경하지 않고 마음대로 변경할 수있는 구현 세부 사항이 숨겨져 있다는 것입니다. 예제 코드의 경우 :

def public_func(a):
    b = _do_stuff(a)
    return _do_more_stuff(b)

을 사용하는 일련의 테스트가있는 public_func경우 다음과 같이 다시 작성하십시오.

def public_func(a):
    b = _do_all_the_new_stuff(a)
    return _do_all_the_old_stuff(b)

그런 다음 특정 값에 대한 반환 결과 a가 동일하게 유지되는 한 모든 테스트가 양호합니다. 반환 결과가 변경되면 테스트가 실패하여 문제가 발생했음을 강조합니다.

이것은 모두 좋은 것입니다 : 정적 공개 API; 잘 캡슐화 된 내부 작업; 강력한 테스트.

당신이 테스트를 작성했던 경우, _do_stuff또는 _do_more_stuff다음 위의 변화를 만들어, 당신은 지금 기능이 변경되지 때문에, 깨진 테스트의 무리를 가지고 싶지만, 그 기능의 구현이 변경 때문이다. 이러한 테스트는 새로운 기능으로 작동하려면 다시 작성해야하지만 작동하게되면 테스트가 새로운 기능으로 작동한다는 것만 알 수 있습니다. 원래 테스트를 잃었으므로 동작 public_func이 변경 되었는지 알 수 없으므로 기본적으로 테스트가 쓸모가 없습니다.

이것은 나쁜 것입니다 : API 변경; 테스트에 밀접하게 연결된 노출 된 내부 작업; 구현이 변경되는 즉시 변경되는 취성 테스트

따라서 개인 기능을 테스트하지 마십시오. 이제까지.


안녕하세요 데이빗, 답변 주셔서 감사합니다. 내 질문을 다시 읽으십시오. 명확히하기 위해 편집했습니다.
Aviv Cohn 2016

Meh. 내부 기능 테스트에는 아무런 문제가 없습니다. 필자는 개인적으로 몇 가지 단위 테스트로 다루지 않는 한 사소한 기능을 작성하지 않으므로 내부 함수에 대한 테스트를 금지하면 내부 함수를 작성하지 못하게되어 매우 유용한 기술을 빼앗을 수 없습니다. API는 변화 할 수 있고 변화합니다. 그들이 할 때, 당신은 테스트를 변경해야합니다. 내부 함수 (및 테스트)를 리팩토링해도 외부 함수의 테스트는 중단되지 않습니다. 그것이 그 테스트의 핵심입니다. 전반적으로 나쁜 조언.
Robert Harvey

당신이 정말로 주장하는 것은 개인 기능이 없어야한다는 것입니다.
Robert Harvey

1
@AvivCohn 그들은 테스트를 보증하기에 충분히 크며,이 경우에는 자신의 파일을 얻을 수있을만큼 크다. 또는 크기가 작아서 별도로 테스트 할 필요가 없습니다. 그래서 어느 것입니까?
Doval

3
@RobertHarvey 아니요, "필요한 경우 큰 클래스를 느슨하게 결합 된 구성 요소로 나눕니다"라는 주장을합니다. 그들은 있다면 정말 아마 패키지 개인 가시성 좋은 사용이 사건이 공개되지.
Doval
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.