단위 테스트를 위해 개인용 메소드를 공개하는 것은 좋은 생각입니까? 이것은 메서드가

중재자 참고 : 여기에 이미 39 개의 답변이 게시되어 있습니다 (일부는 삭제되었습니다). 답변 을 게시하기 전에 토론에 의미있는 것을 추가 할 수 있는지 여부를 고려 하십시오 . 다른 사람이 이미 말한 것을 반복했을 가능성이 높습니다.


가끔 단위 테스트를 작성하기 위해 클래스 공용에서 개인용 메소드를 작성해야하는 경우가 있습니다.

일반적으로 이것은 메서드가 클래스의 다른 메서드간에 공유되는 논리를 포함하고 자체적으로 논리를 테스트하기가 더 어렵 기 때문에 또는 스레드 문제에 대해 걱정할 필요없이 동기식 스레드에서 사용되는 논리를 테스트하고 싶을 수도 있습니다. .

다른 사람들이 스스로하는 일을합니까? 왜냐하면 저는 그 일을 정말 좋아하지 않기 때문입니다 ?? 개인적으로 보너스는 클래스 외부에서 서비스를 제공하지 않는 메소드를 공개하는 문제보다 중요하다고 생각합니다 …

최신 정보

모두에게 답변을 주셔서 감사합니다, 사람들의 관심을 끌고있는 것 같습니다. 클래스가 사용될 유일한 방법이기 때문에 퍼블릭 API를 통해 테스트를 수행해야한다는 일반적인 합의가 있다고 생각합니다. 위에서 언급 한 두 가지 사례는 흔하지 않은 사례였으며 그로 인해 얻을 수있는 이점이 가치 있다고 생각했습니다.

그러나 모든 사람들이 결코 그런 일이 일어나지 않아야한다는 점을 알 수 있습니다. 그리고 조금 더 생각할 때 테스트를 수용하기 위해 코드를 변경하는 것은 나쁜 생각이라고 생각합니다. 결국 테스트가 일종의 지원 도구라고 생각하고 시스템을 ‘지원 도구를 지원하도록’변경하는 것이 뻔하다 고 생각합니다. 나쁜 연습.



답변

참고 :
이 답변은 원래 질문에 대해 게시되었습니다. 단위 테스트만으로도 getter를 통해 프라이빗 인스턴스 변수를 노출해야하는 좋은 이유가 있습니까? 이것은 이것과 합쳐져서, 여기에 제시된 유스 케이스에 특유한 것이 될 수 있습니다.

일반적인 설명으로, 나는 보통 테스트하기 쉽도록 “프로덕션”코드를 리팩토링하는 일을합니다. 그러나 나는 이것이 좋은 전화라고 생각하지 않습니다. 좋은 단위 테스트는 (보통) 클래스의 구현 세부 사항, 가시적 인 동작에만 신경 쓰지 않아야합니다. 대신 시험에 내부 스택을 노출, 당신은 클래스를 사용하면 호출 한 후 그것을 기대하는 순서로 페이지를 반환하는지 테스트 할 수 first()또는 last().

예를 들어 다음 의사 코드를 고려하십시오.

public class NavigationTest {
    private Navigation nav;

    @Before
    public void setUp() {
        // Set up nav so the order is page1->page2->page3 and
        // we've moved back to page2
        nav = ...;
    }

    @Test
    public void testFirst() {
        nav.first();

        assertEquals("page1", nav.getPage());

        nav.next();
        assertEquals("page2", nav.getPage());

        nav.next();
        assertEquals("page3", nav.getPage());
    }

    @Test
    public void testLast() {
        nav.last();

        assertEquals("page3", nav.getPage());

        nav.previous();
        assertEquals("page2", nav.getPage());

        nav.previous();
        assertEquals("page1", nav.getPage());
    }
}


답변

개인적으로, 나는 대중 API를 사용하지 않고 단위 테스트를 거라고 나는 확실히 개인 방법 공개는하지 않습니다 않겠다고 단지 시험에 쉽게 그것을 만들 수 있습니다.

개인 메소드를 분리하여 테스트하고 싶다면 Java에서 Easymock / Powermock 을 사용하여이를 수행 할 수 있습니다.

당신은 그것에 대해 실용적이어야하고 또한 사물을 테스트하기 어려운 이유를 알고 있어야합니다.

테스트 듣기 ‘-테스트하기 어려운 경우 디자인에 대해 이야기하고 있습니까? 이 방법에 대한 테스트가 사소하고 공개 API를 통한 테스트로 쉽게 다루어지는 위치를 리팩터링 할 수 있습니까?

여기에 무엇 마이클 깃털 것은 ‘에 말을 가지고있어 효과적으로 레거시 코드로 작업

“많은 사람들 이이 문제를 해결하는 방법을 알아 내려고 많은 시간을 소비합니다 … 실제 답변은 개인 방법을 테스트 해야하는 충동이 있다면 방법이 비공개가되어서는 안된다는 것입니다. “당신을 귀찮게 할 것입니다. 그것은 별도의 책임의 일부이기 때문입니다. 다른 반에 있어야합니다.” [ M. Feathers의 레거시 코드 (2005)로 효과적으로 작업 ]


답변

다른 사람들이 말했듯이, 개인 메소드를 단위 테스트하는 것이 다소 의심됩니다. 개별 구현 세부 정보가 아닌 공개 인터페이스를 단위 테스트합니다.

즉, C #에서 개인 단위로 테스트 할 때 사용하는 기술은 액세스 가능성 보호를 개인에서 내부로 다운 그레이드 한 다음 InternalsVisibleTo 사용하여 친구 테스트로 단위 테스트 어셈블리를 표시하는 것 입니다. 그러면 단위 테스트 어셈블리가 내부를 공개로 취급 할 수 있지만 실수로 공개 표면 영역에 추가하는 것에 대해 걱정할 필요는 없습니다.


답변

많은 답변은 공개 인터페이스 테스트 만 제안하지만 IMHO 이것은 비현실적입니다. 메서드가 5 단계를 수행하는 작업을 수행하는 경우 5 단계를 모두 테스트하지 않고 별도로 테스트해야합니다. 이 모든 다섯 가지 방법, 시험이 필요합니다 (테스트 이외의) 다른 수 있습니다을 private.

“비공개”메소드를 테스트하는 일반적인 방법은 모든 클래스에 고유 한 인터페이스를 부여하고 “비공개”메소드 public를 작성하지만 인터페이스에는 포함시키지 않는 것입니다. 이런 식으로, 그들은 여전히 ​​테스트 할 수 있지만 인터페이스를 팽창시키지 않습니다.

예, 이렇게하면 파일과 클래스가 팽창합니다.

예, 이렇게하면 publicprivate지정자가 중복됩니다.

예, 이것은 엉덩이에 통증이 있습니다.

불행히도 이것은 코드를 테스트 할 수있게 만드는 많은 희생 중 하나입니다 . 아마도 미래 언어 (또는 미래 버전의 C # / Java)에는 클래스 및 모듈 테스트 가능성을보다 편리하게 만드는 기능이있을 것입니다. 그러나 그 동안 우리는이 후프를 뛰어 넘어야합니다.


각 단계가 자신의 클래스 여야한다고 주장하는 사람들도 있지만 동의하지 않습니다. 모두 공유 상태라면 5 가지 방법으로 5 가지 클래스를 만들 이유가 없습니다. 더 나쁜 것은 이로 인해 파일 및 클래스 팽창이 발생한다는 것입니다. 또한 모듈의 공개 API를 감염시킵니다. 다른 모든 클래스 public에서 테스트하려는 경우 해당 클래스가 있어야합니다 (또는 테스트 코드를 동일한 모듈에 포함 시키므로 테스트 코드를 제품과 함께 제공함). .


답변

단위 테스트는 클래스의 다른 부분에서 클래스를 사용하는 유일한 방법 인 공개 계약을 테스트해야합니다. 비공개 메소드는 구현 세부 사항이므로 공개 API가 올바르게 작동하는 한 테스트 사례를 변경하지 않고 구현이 중요하지 않고 변경 될 수있는 경우 테스트하지 않아야합니다.


답변

IMO, 당신은 당신의 클래스가 어떻게 구현되었는지에 대해 깊이 가정하지 않는 테스트를 작성해야합니다. 나중에 다른 내부 모델을 사용하여 리팩토링하고 싶을 수도 있지만 이전 구현에서 제공하는 것과 동일한 보장을 계속합니다.

이를 염두에 두면서 현재 클래스의 내부 구현에 관계없이 계약이 여전히 유지되고 있는지 테스트하는 데 집중하는 것이 좋습니다. 퍼블릭 API의 속성 기반 테스트.


답변

비공개 패키지로 만드는 것은 어떻습니까? 그런 다음 테스트 코드에서 코드 및 패키지의 다른 클래스를 볼 수 있지만 여전히 사용자에게 숨겨져 있습니다.

그러나 실제로는 개인 메소드를 테스트해서는 안됩니다. 이는 구현 세부 사항이며 계약의 일부가 아닙니다. 그들이하는 모든 것은 공개 메소드를 호출하여 다루어야합니다 (공개 메소드로 실행되지 않는 코드가있는 경우 계속 진행해야 함). 개인 코드가 너무 복잡하면 클래스가 너무 많은 일을하고 리팩토링을 원할 것입니다.

메소드를 공개하는 것은 큰 노력입니다. 일단 그렇게하면 사람들은 그것을 사용할 수 있으며 더 이상 변경할 수 없습니다.