[unit-testing] 게터와 세터에 대해 단위 테스트를 작성해야합니까?

게터와 세터에 대한 테스트를 작성해야합니까, 아니면 과잉입니까?



답변

나는 아니오라고 말할 것입니다.

@ 윌은 100 % 코드 범위를 목표로 삼아야한다고 말했지만 내 생각에는 위험한 혼란입니다. 적용 범위가 100 % 인 단위 테스트를 작성할 수 있지만 전혀 테스트 할 수는 없습니다.

단위 테스트는 표현적이고 의미있는 방식으로 코드의 동작을 테스트하기 위해 제공되며 게터 / 세터는 끝의 수단 일뿐입니다. 테스트에서 getter / setter를 사용하여 “실제”기능을 테스트한다는 목표를 달성하면 충분합니다.

반면에, getter와 setter가 단지 get and set 이상의 기능을 수행하는 경우 (즉, 적절하게 복잡한 방법) 테스트를 받아야합니다. 그러나 단위 테스트 케이스를 작성하지 않는 단지 시간 낭비 게터 또는 세터를 테스트합니다.


답변

Roy Osherove는 그의 유명한 저서 ‘The Art Of Unit Testing’에서 다음과 같이 말합니다.

속성 (Java의 getter / setter)은 일반적으로 로직을 포함하지 않으며 테스트 할 필요가없는 코드의 좋은 예입니다. 그러나 조심하십시오 : 일단 속성 내부에 검사를 추가하면 논리가 테스트되고 있는지 확인해야합니다.


답변

TDD와 함께 울리는 YES


참고 :이 답변은 잠재적으로 나쁜 조언이기는하지만 계속 upvotes를 얻습니다. 이유를 이해하려면 아래의 여동생을 살펴보십시오 .


논란의 여지가 있지만, 나는이 질문에 ‘아니오’라고 대답하는 사람은 TDD의 기본 개념이 누락되었다고 주장합니다.

나를 위해, 대답은 울려 퍼지는이다 예는 는 TDD를 수행합니다. 그렇지 않다면 그럴듯한 대답은 없습니다.

TDD의 DDD

TDD는 종종 주요 이점이 있다고 인용됩니다.

  • 방어
    • 코드가 변경 될 수 있지만 동작 이 변경 되지 않도록 보장 .
    • 이것은 리팩토링의 매우 중요한 관행을 허용합니다 .
    • 이 TDD를 얻거나 얻지 못합니다.
  • 디자인
    • 당신은 지정 무엇인가, 어떻게의 동작을해야 무엇을해야 구현하기 전에 그것을.
    • 이것은 종종보다 현명한 구현 결정을 의미 합니다.
  • 선적 서류 비치
    • 테스트 스위트는 사양 으로 사용되어야합니다 (요구 사항) 문서 .
    • 그러한 목적으로 테스트를 사용한다는 것은 문서와 구현이 항상 일관된 상태임을 의미합니다. 하나를 변경하면 다른 것으로 변경됩니다. 별도의 워드 문서에서 요구 사항과 디자인을 유지하는 것과 비교하십시오.

구현과 별도의 책임

프로그래머로서, 속성을 중요성과 게터로 생각하고 일종의 오버 헤드로 세터를 생각하는 것은 대단히 유혹적입니다.

그러나 속성은 구현 세부 사항이며 세터와 게터는 실제로 프로그램을 작동시키는 계약 인터페이스입니다.

객체가 다음과 같이 철자를 작성하는 것이 훨씬 더 중요합니다.

클라이언트가 상태를 변경하도록 허용

클라이언트가 상태를 쿼리하도록 허용

그런 다음이 상태가 실제로 저장되는 방법 (속성이 가장 일반적이지만 유일한 방법은 아닙니다).

다음과 같은 테스트

(The Painter class) should store the provided colour

TDD 의 문서 부분에 중요합니다 .

테스트를 작성할 때 최종 구현이 사소한 (속성) 방어 이점 이 없다는 사실을 알 수 없습니다.

왕복 공학의 부족 …

시스템 개발 세계의 주요 문제 중 하나는 왕복 공학 의 부족입니다. 1- 시스템의 개발 프로세스가 분리 된 하위 프로세스로 분할됩니다 (문서, 코드).

1 브로디, 마이클 L. “존 마일로 풀 로스 : 개념적인 모델링의 재봉 씨.” 개념 모델링 : 기초 및 응용. Springer Berlin Heidelberg, 2009. 1-9.

… 그리고 TDD가이를 해결하는 방법

시스템 및 해당 코드의 스펙이 항상 일관되도록 TDD 의 문서 부분입니다.

먼저 디자인하고 나중에 구현

TDD 내에서 먼저 합격 합격 테스트를 작성한 다음 통과 할 수있는 코드 만 작성하십시오.

높은 수준의 BDD 내에서 먼저 시나리오를 작성한 다음 통과시킵니다.

왜 세터와 게터를 제외시켜야합니까?

이론적으로 TDD 내에서 한 사람이 테스트를 작성하고 다른 사람이 테스트를 통과시키는 코드를 구현할 수 있습니다.

그러므로 스스로에게 물어보십시오 :

클래스 테스트를 작성하는 사람이 getter 및 setter를 언급해야합니다.

getter와 setter는 클래스에 대한 공용 인터페이스이므로 대답은 명백히 yes 이거나 객체의 상태를 설정하거나 쿼리 할 방법이 없습니다. 그러나이 작업을 수행하는 방법이 각 방법을 개별적으로 테스트하는 것은 아닙니다 . 자세한 내용은 다른 답변 을 참조하십시오.

분명히 코드를 먼저 작성하면 답이 명확하지 않을 수 있습니다.


답변

TL; 박사 : 당신이 해야 하고, 함께 OpenPojo 사소한입니다.

  1. 게터와 세터에서 약간의 유효성 검사를 수행해야하므로 테스트해야합니다. 예를 들어, setMom(Person p)자신보다 어린 사람을 어머니로 설정해서는 안됩니다.

  2. 지금도 그 일을하고 있지 않더라도 미래에 일어날 확률은 회귀 분석에 도움이 될 것입니다. 당신이 어머니를 설정하게하려는 경우 null, 나중에 누군가가 그것을 바꿀 수 있는지 테스트해야합니다. 그러면 당신의 가정이 강화 될 것입니다.

  3. 일반적인 버그는 void setFoo( Object foo ){ foo = foo; }어디에 있어야 하는가void setFoo( Object foo ){ this.foo = foo; } . (첫 번째 경우 foo에 작성되는 것은 오브젝트 의 필드가 아닌 매개 변수입니다 ).foo

  4. 배열이나 컬렉션을 반환하는 경우 getter가 반환하기 전에 setter로 전달 된 데이터의 방어 복사본 을 수행 할 것인지 테스트해야합니다 .

  5. 그렇지 않으면 가장 기본적인 세터 / 게터가 있다면 단위 테스트를 수행하면 객체 당 최대 10 분 정도가 추가되므로 손실은 무엇입니까? 동작을 추가하면 이미 골격 테스트를 받았으며이 회귀 테스트를 무료로받을 수 있습니다. Java를 사용하는 경우 OpenPojo있으므로 변명의 여지가 없습니다 . 사용 가능한 기존 규칙 세트가 있고 전체 프로젝트를 스캔하여 규칙 내에서 일관되게 적용되도록 할 수 있습니다.

그들의 예에서 :

final PojoValidator pojoValidator = new PojoValidator();

//create rules
pojoValidator.addRule( new NoPublicFieldsRule  () );
pojoValidator.addRule( new NoPrimitivesRule    () );
pojoValidator.addRule( new GetterMustExistRule () );
pojoValidator.addRule( new SetterMustExistRule () );

//create testers
pojoValidator.addTester( new DefaultValuesNullTester () );
pojoValidator.addTester( new SetterTester            () );
pojoValidator.addTester( new GetterTester            () );

//test all the classes
for(  PojoClass  pojoClass :  PojoClassFactory.getPojoClasses( "net.initech.app", new FilterPackageInfo() )  )
    pojoValidator.runValidation( pojoClass );


답변

예, 항상 고립 된 것은 아닙니다

정교하게 해주세요 :

단위 테스트 란 무엇입니까?

에서 레거시 코드를 효과적으로 작업을 1 :

단위 테스트라는 용어는 소프트웨어 개발에서 오랜 역사를 가지고 있습니다. 단위 테스트의 대부분의 개념에 공통되는 것은 소프트웨어의 개별 구성 요소를 분리 한 테스트라는 개념입니다. 구성 요소 란 무엇입니까? 정의는 다양하지만 단위 테스트에서는 일반적으로 시스템의 가장 원자적인 동작 단위에 관심이 있습니다. 절차 코드에서 단위는 종종 기능입니다. 객체 지향 코드에서 단위는 클래스입니다.

getter와 setter를 찾는 OOP를 사용하면 단위는 클래스 이며 반드시 개별 메소드는 아닙니다. 입니다.

좋은 시험은 무엇입니까?

모든 요구 사항 및 테스트는 Hoare 로직 의 형식을 따릅니다 .

{P} C {Q}

어디:

  • {P}전제 조건입니다 ( 주어진 )
  • C트리거 조건입니다 ( when )
  • {Q}사후 조건이다 ( then )

그런 다음 최대가됩니다.

구현이 아닌 테스트 동작

C, 사후 조건을 달성하는 방법을 테스트하지 말고 {Q}그 결과인지 확인해야합니다 C.

OOP에 관해서 C는 클래스입니다. 따라서 내부 효과는 테스트하지 말고 외부 효과 만 테스트해야합니다.

왜 빈 게터와 세터를 따로 테스트하지 않는가?

게터와 세터는 약간의 로직을 포함 할 수 있지만, 너무 오래이 논리는 외부 효과가 없습니다 – 그들을 만드는 콩 접근 (2) 자를 ) 테스트는 객체 내부를 살펴 봐야합니다.

따라서 빈 getter와 setter를 분리해서 테스트해서는 안됩니다. 이것은 나쁘다 :

Describe 'LineItem class'

    Describe 'setVAT()'

        it 'should store the VAT rate'

            lineItem = new LineItem()
            lineItem.setVAT( 0.5 )
            expect( lineItem.vat ).toBe( 0.5 )

경우 만 setVAT예외를 슬로우 해주기 때문에, 해당 테스트는 적절한 것 외부 효과.

게터와 세터를 어떻게 테스트해야합니까?

이러한 효과가 나중에 영향을 주더라도 외부에 영향을 미치지 않으면 객체의 내부 상태를 변경하는 지점은 거의 없습니다.

따라서 세터와 게터에 대한 테스트는 내부 메소드가 아닌 이러한 메소드의 외부 효과에 대해 고려해야합니다.

예를 들면 다음과 같습니다.

Describe 'LineItem class'

    Describe 'getGross()'

        it 'should return the net time the VAT'

            lineItem = new LineItem()
            lineItem.setNet( 100 )
            lineItem.setVAT( 0.5 )
            expect( lineItem.getGross() ).toBe( 150 )

당신은 자신에게 생각할 수 있습니다 :

잠깐만, 우리는 getGross()여기서 테스트 하지 않습니다 setVAT() .

그러나 setVAT()오작동 인 경우 해당 테스트는 모두 동일하게 실패합니다.

1 Feathers, M., 2004. 레거시 코드로 효과적으로 작업합니다. 프렌 티스 홀 프로페셔널.

2 Martin, RC, 2009. 깨끗한 코드 : 민첩한 소프트웨어 장인의 핸드북. 피어슨 교육.


답변

속성에 대한 정당한 이유가 있지만 속성을 통해 멤버 상태를 노출하는 것은 잘못된 디자인이라는 일반적인 객체 지향 디자인의 믿음이 있습니다. 공개 폐쇄 원칙에 대한 Robert Martin의 기사 는 속성이 커플 링을 권장하므로 클래스를 수정하지 못하도록 제한하는 기능을 제한함으로써이를 확장합니다. 속성을 수정하면 클래스의 모든 소비자도 변경해야합니다. 그는 멤버 변수를 노출하는 것이 반드시 나쁜 디자인 일 필요는 없으며 스타일이 좋지 않을 수도 있다고 규정합니다. 그러나 속성이 읽기 전용 인 경우 남용 및 부작용이 적습니다.

단위 테스트에 제공 할 수있는 가장 좋은 방법은 가능한 한 많은 속성을 보호하거나 내부적으로 만드는 것입니다. 이렇게하면 게터와 세터에 대한 바보 같은 테스트를 작성하지 말고 커플 링을 방지 할 수 있습니다.

입력 필드에 바인딩 된 ViewModel 속성과 같이 읽기 / 쓰기 속성을 사용해야하는 분명한 이유가 있습니다.

보다 실질적으로, 단위 테스트는 공개 방법을 통해 기능성을 주도해야합니다. 테스트중인 코드가 해당 속성을 사용하는 경우 코드 적용 범위가 무료입니다. 이러한 속성이 코드 커버리지로 강조 표시되지 않는 경우 다음과 같은 가능성이 매우 높습니다.

  1. 속성을 간접적으로 사용하는 테스트가 누락되었습니다
  2. 속성이 사용되지 않습니다

getter 및 setter에 대한 테스트를 작성하면 적용 범위가 잘못되어 실제로 기능적 동작에 의해 특성이 사용되는지 여부를 판별 할 수 없습니다.


답변

게터 및 / 또는 세터 의 순환 복잡도 가 1 (일반적으로있는 경우)이면 대답은 ‘아니오’입니다.

따라서 100 % 코드 적용이 필요한 SLA가 없다면 소프트웨어의 중요한 측면을 테스트하는 데 신경 쓰지 말고 집중하십시오.

PS 속성이 같은 것처럼 보일 수있는 C #과 같은 언어에서도 게터와 세터를 구분해야합니다. 세터 복잡도는 게터보다 높을 수 있으므로 단위 테스트의 유효성을 검사합니다.