TDD에서 먼저 테스트 나 인터페이스를 먼저 써야합니까?


23

내가 아는 한 나는까지, C #을 사용 TDD를 배우고 시험을 개발 운전해야 하고, 먼저 쓰기를 실패하는 테스트 기입 후 최소한의 다음 리팩토링 않는 테스트를 통과하는 코드를.

그러나 " 구현이 아닌 인터페이스에 대한 프로그램 "이라고 말하면 먼저 인터페이스를 작성하십시오 . 이것은 혼란이 시작되는 곳입니다. 인터페이스를 먼저 작성하면 두 가지를 위반하는 것입니다.

  1. 인터페이스 용으로 작성된 코드는 test에 의해 구동되지 않습니다 .

  2. 분명히 간단한 클래스로 쓸 수있는 최소한의 것은 아닙니다 .

인터페이스 테스트도 작성해야합니까? 구현하지 않고 테스트 할 내용은 무엇입니까?

이 질문이 유감스럽게 들리지만 완전히 혼란 스럽습니다. 문자 그대로 너무 많이 가져갈 수 있습니다.


8
"인터페이스에 대한 프로그램"이란 코드에서 필요한 것을 분리하는 방법을 분리하는 것을 의미합니다. 문자 그대로 interface모든 것을 사용한다는 의미는 아닙니다 . A는 class당신이 구현 세부 사항 숨길 수 있기 때문에 또한, 인터페이스를 제공 private변수를.
Doval

@Doval, 그렇습니다. 모든 것에 대한 인터페이스가 필요하지 않습니다 contract. 예를 들어 추상 클래스의 형태 일 수 있지만 인스턴스화 할 수 없어 가상 클래스 / 메서드가 아니어야합니다.
trysis

2
TDD는 "실패한 테스트를 작성하십시오"라고 말합니다. 일부 엄격한 TDDer 는 작동하는 데이터 유형이 아직 선언되지 않았기 때문에 테스트를 컴파일 할 수없는 경우 "실패"로 계산한다고 말합니다 .
Solomon Slow

답변:


29

첫 번째 위반 ( "인터페이스 용으로 작성된 코드는 테스트로 구동되지 않습니다.")이 유효하지 않습니다. 사소한 예를 사용합시다. 계산기 클래스를 작성하고 추가 연산을 작성한다고 가정하십시오. 어떤 시험을 쓸 수 있습니까?

public class CalculatorTest {
    @Test
    public void testAddTwoIntegers() {
        Calculator calc = new Calculator();
        int result = calc.add(2, 2)
        Assert.assertEquals(4, result);
    }
}

테스트에서 인터페이스를 정의했습니다. 그것은이다 add방법을 참조하십시오? add두 개의 인수를 사용하여 합계를 반환합니다. 나중에 여러 계산기가 필요하다고 판단하고 그 시점에서 (이 경우) Java 인터페이스를 추출 할 수 있습니다. 해당 클래스공용 인터페이스 를 테스트 했으므로 테스트가 변경되지 않아야합니다 .

보다 이론적 인 수준에서 테스트는 시스템의 실행 가능한 사양입니다. 시스템에 대한 인터페이스는 해당 시스템의 사용자가 주도해야하며 테스트는 상호 작용을 정의하는 첫 번째 방법입니다.

인터페이스 디자인과 테스트 디자인을 분리 할 수 ​​있다고 생각하지 않습니다. 그들을 위해 상호 작용을 정의하고 설계 테스트는 같은 마음으로 작업을하다 - 내가 인터페이스에이 정보를 보내, 내가 기대하는 어떤 결과를. 뭔가 내 입력에 문제가 있습니다, 내가 예상 이 오류를. 이 디자인 작업을 종이에 적용한 다음 그로부터 테스트를 작성하거나 동시에 테스트를 수행 할 수 있습니다. 실제로 중요하지 않습니다.


2
+1 " 테스트 디자인과 인터페이스 디자인을 분리 할 수 ​​없다고 생각합니다. "굵게 표시해야합니다. IMHO :)
Binary Worrier

XML 가져 오기 및 CSV 가져 오기는 기능의 구현을 둘 이상 테스트하려는 경우 구현이 변경 되더라도 동일한 인터페이스에서 정확히 동일한 방법으로 테스트 할 수 있다고 표시하는 것이 훨씬 더 쉽습니다. 또한 테스트에는 종종 조롱이 필요하며이 인터페이스에는 필요합니다.
Walfrat

테스트를 변경할 필요 new Calculator()는 없지만 구현은 맞습니까? 새로운 구현이 필요한 경우 MultiplicationCalculator를 수행하고 테스트 new AdditionCalculator()를 계속 통과 하기 위해 테스트를 변경 해야합니까? 아니면 뭔가 빠졌습니까?
Steve Chamaillard

3
@SteveChamaillard 물론, 디자인에서 클래스 이름을 계산기에서 AdditionCalculator로 변경하면 테스트가 일치하도록 변경해야합니다. 물론, TDD를 수행함으로써 실제로 일어날 일은 테스트를 먼저 변경하고 클래스 변경은 테스트를 통과하기 위해 따릅니다.
Eric King

5

우리가 글을 쓸 때 무엇을하고 interface있습니까? 우리는 코드를 작성 하고 있습니까 , 아니면 디자인하고 있습니까?

저는 Test Driven Design이라는 개념의 팬이 아니지만 Test Driven Development를 좋아 합니다. 개인적으로 테스트를 작성하기 전에 인터페이스를 디자인하여 클래스를 미리 디자인 할 때 최상의 결과를 얻었습니다. 인터페이스를 코드로 계산하지 않습니다. 인터페이스는 TDD를 사용하여 구현할 디자인입니다. 내가 일하면서 진화를 바꿀 가능성이 있지만 (내 테스트 목록과 함께) 나의 로드맵입니다.

내가 울기 시작하기 전에 멈출 것이지만, 그것이 당신이 그것에 대해 생각할 수있는 유용한 방법이되기를 바랍니다.


4

TDD에서 먼저 테스트 나 인터페이스를 먼저 써야합니까?

그것은 모두 당신이 TDD 를하기를 원하는 정통 / 종교에 달려 있습니다.

나는 TDD를 배우고있다

배우는 동안 개인 워크 플로를 시험해보아야합니다.

  1. 책에 따라 하고 싶다면 처음에는 테스트를 작성하십시오. 코드가 전혀 없기 때문에 실패 할 것입니다. 그런 다음 테스트를 통과시키기위한 코드를 작성합니다. 그렇게하면 리팩토링을위한 일종의 안전망을 제공하는 테스트가 있으므로 기존 코드를 리팩터링 할 수 있습니다. 인터페이스 사용을 결정하는 것은 일종의 리팩토링입니다.

  2. TDD 외에도 : 인터페이스 사용 여부는 처음에는 흥미롭지 않습니다. 물론 확실하다면 여러 객체에 다른 동작을 퍼 뜨리고 싶다면 인터페이스를 사용하는 것이 좋습니다. 인터페이스 Writer 로, 출력에 대한 다른 클래스가 있습니다 ( FileWriter , Printer 등). 인터페이스쓰는 것이 일반적 이지만, 모든 것을 위해 인터페이스를 사용 한다는 의미는 아닙니다 . 때때로 그것은 많은 것에 대한 간접적 인 수준입니다. Btw. 서비스도 마찬가지입니다. 그러나 그것은 다른 주제입니다.

  3. 반면 에 다른 방법으로 테스트 중심의 테스트를 개발할 수 있습니다 . 테스트 가능성을위한 코드 디자인. 즉, 나중에 테스트를 작성하더라도 테스트하기 쉬운 코드를 작성한다는 의미 입니다. 어쨌든 테스트하는 한, 미리 또는 나중에 테스트를 작성하는 것은 중요하지 않습니다.


5
마지막 요점에 동의 할 수 없습니다 "어쨌든 테스트하는 한, 미리 또는 나중에 테스트를 작성해도 문제가되지 않습니다." 나중에 테스트를 작성하면 테스트가 올바른 테스트인지 확인할 수 없습니다.
k4vin

4
내가 말했듯이 ... 그것은 ... 당신이 얼마나 정통에 따라 달라집니다
토마스 정크

2

TDD 또는 BDD는 도메인 인터페이스를 먼저 수행 한 다음 해석을 통해 도메인 인터페이스에 대한 테스트를 작성하는 것을 의미합니다. 인터페이스 구현에는 예상 된 동작이 있습니다.

인터페이스는 테스트 가능한 로직을 포함하지 않기 때문에 코드보다 먼저 테스트되지만 테스트를 작성하는 구조입니다.

나는 다음과 같이 할 것입니다

  1. 반 정식 행동 작성 (Given : When : Then :)

  2. 인터페이스 작성 (행동 캡슐화 방법을 호스트하기 위해)

  3. 식별 테스트를 작성하십시오 (주어진 입력, 호출, 그때 테스트)

  4. 테스트를 통과하기 위해 콘크리트 (인터페이스를 구현하는 클래스)를 작성 / 변경


0

인터페이스를 설계하기 전에 테스트를 작성하지 마십시오. 작성할 테스트 종류 (테스트 디자인)에 대해 생각할 때 응용 프로그램을 동시에 디자인 (아키텍처)해서는 안됩니다. 두 가지를 동시에 생각하지 마십시오. 우려의 분리에 대해 들어 보셨습니까? 그것은 코드의 물리적 구조뿐만 아니라 사고 과정에도 적용됩니다.

응용 프로그램을 먼저 디자인하는 방법을 결정하십시오. 즉, 인터페이스와 이러한 인터페이스 간의 관계를 설계해야합니다. 이 작업을 수행 할 때까지 테스트에 대해 생각하지 않아야합니다. 인터페이스가 무엇인지 알면 먼저 인터페이스를 생성 한 다음 테스트를 작성하거나 테스트를 작성한 다음 작성할 수 있습니다. 후자의 경우 분명히 테스트를 컴파일 할 수 없습니다. 테스트 전에 인터페이스를 만들 때 TDD 철학을 위반하거나 해를 입히지 않습니다.


에서 추론 최고 응답 더욱 매력적인 외모 : "나는 당신이 시험 디자인과 인터페이스 디자인을 분리 할 수 있다고 생각하지 않습니다 상호 작용을 정의하고 그들을 위해 테스트를 설계 같은 마음으로 작업을하다 -. 내가 인터페이스에이 정보를 보내, 내가 기대하는 어떤 결과를 . 뭔가 내 입력에 문제가 있습니다, 내가 예상 이 오류 ... "
모기

@gnat 여기서 Nissam interface은 일반적인 용어 "인터페이스"가 아니라 C # 키워드를 언급하고 있다고 생각 합니다.
RubberDuck

@RubberDuck 또한 그렇게 생각하며 이것이 나쁜 접근 방식이라고 생각합니다. "이 작업을 완료하기 전에는 테스트에 대해 생각하지 말아야합니다 ..."내가 썼 듯이, 최상위 답변에 대한 추론은 일반적인 인터페이스와 구체적인 키워드의 의미에서 더 매력적으로 보입니다.
gnat

귀하의 의견에서 명확하지 않은 충분한 @gnat. 개인적으로, 나는 여기 Nissam에 동의합니다. 사람들이 TDD를 전혀 디자인하지 않기위한 변명으로 사용하지 못하게합니다. YMMV.
RubberDuck

-2

인터페이스가 프로젝트에 통합되어있는 한 인터페이스 / 코드 / 테스트를 작성하는 것은 괜찮습니다.

상사가 TDD에 대해 종교적 인 경우를 제외하고는 빈 인터페이스를 작성해야합니다-> 테스트-> 최소 코드 (무의미한 단계)-> 더 많은 테스트-> 더 의미없는 코드-> 더 많은 테스트-> 마침내 실제 코드 작성- > 완료.

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