테스트 주도 개발 : 파일 시스템 운영을 테스트하는 좋은 방법?


14

나는 현재 파일 시스템의 내용을 기반으로 테이블을 생성하는 프로젝트를 진행하고 있으며 찾은 것들에 대한 메타 데이터 수정을 수행합니다. 문제는 어떻게 테스트를 작성하거나 설정해야합니까? 이것을 조롱하는 쉬운 방법이 있습니까? 아니면 "샌드 박스"를 설정해야합니까?

답변:


13

항상 외부 자원과 함께 TDD에서와 같이 파일 시스템 조작에 대한 하나 이상의 인터페이스를 작성하고 "모방"합니다. 파일 시스템 작업 자체가 아니라 "테이블 생성기"와 메타 데이터 수정 코드를 테스트하려고합니다 (파일 시스템에 액세스하기 위해 기성품 라이브러리 구현을 사용하고있을 것입니다).


TDD는 테스트중인 유닛의 구현을 조롱하지 않는 것이 좋습니다. (예 : solnic.eu/2014/05/22/mocking-and-ruby.html 참조
soru

1
@ soru :이 답변이 권장하는 것은 아닙니다. 먼저 다음 조롱 인터페이스를 생성 권장 인터페이스 . 따라서 비즈니스 로직은 테스트하지만 파일 시스템 인터페이스는 테스트하지 않습니다.
sleske

5
그러나 비즈니스 로직이 파일과 디렉토리로 정의 된 것처럼 들립니다. 파일 시스템 API를 호출하는 물건 그래서 입니다 필요가 테스트하는 물건. 관련 비 파일 비즈니스 로직을 테스트 할 때는 조롱 할 필요가 없습니다. 그냥 테스트하십시오.
soru

@ soru, 그래서 모든 도메인 관련 작업이 클라이언트 측에 있고 인터페이스 측이 단위 테스트없이 작동한다는 확신을 가질 정도로 정의 된 인터페이스로 파일 및 폴더 주위에 얇은 계층을 만듭니다 (통합 테스트는 여전히 필요합니다). UI 코드에서 Humble Dialog의 아이디어와 유사하거나 영구 객체에서 작동하는 코드에서 mock Repository를 사용하는 것과 유사합니다.
Jules

2
그래서 우리는 파일 시스템, 데이터베이스 등과 상호 작용하는 실제 클래스 테스트에서 사실상 사임합니다. 대신 모의 / 스텁과 동일한 인터페이스로 다른 구현을 만들지 만 실제 클래스는 단위 테스트없이 떠나고, 단위 테스트를 할 수 없다고 생각하기 때문에 대신 테스트하기 위해 통합 테스트를 수행해야합니다. 이 올바른지?
Andrew Savinykh

11

"테스트"파일 시스템에 문제가 있습니까?

작업을 테스트하기에 충분한 내용이있는 템플릿 폴더 / 디렉토리 구조를 만듭니다.

단위 테스트를 설정하는 동안이 초기 구조를 복사하십시오 (템플릿을 압축하고 테스트 영역으로 압축 해제하는 것이 좋습니다). 테스트를 실행하십시오. 분해하는 동안 모든 것을 삭제하십시오.

조롱 문제는 먼저 프로젝트에 속하는 파일 시스템, OS 및 데이터베이스가 실제로 외부 리소스로 자격이 없으며 둘째로 낮은 수준의 시스템 호출을 조롱하는 데 시간이 걸리고 오류가 발생하기 쉽다는 것입니다.


5
파일 시스템 작업을 모의하면 실제 파일 시스템을 사용하는 것보다 훨씬 빠른 실행 테스트가 생성되며, 이것이 "오류가 발생하기 쉽다"는 것이 구현에 달려 있다고 말할 수 있습니다. 그럼에도 불구하고 자동 통합 테스트 (TDD를하지 않을 때 가장 먼저 수행 할 것) 를 만드는 데 귀하의 제안이 훌륭하다고 생각합니다 . 그러나 OP는 TDD를 명시 적으로 요구했으며 TDD 단위 테스트는 빨라야했습니다.
Doc Brown

1
파일 시스템이 조롱되면 파일 시스템에서 중요한 작업을 수행하는 경우 바퀴를 재발 명하기 때문에 파일 그룹에 이상적으로 그룹에 의해 작성되고 유지되는 전체 API가 있어야한다고 생각합니다.
Frank Hileman

2
@ Doc Brown-나는 그가 조롱하기가 까다로운 경우가있는 유형 작업을 dir, delete 및 이름 바꾸기를 원한다고 가정합니다. 또한 현대 하드웨어에서 디렉토리에 작은 파일 몇 개를 압축 해제하면 Java 클래스를로드하는 것보다 약간 느려집니다.
James Anderson

테스트 파일 시스템에 대해 더 많이 생각할수록 더 좋아합니다.
Frank Hileman

3

실제 파일 시스템에는 모든 종류의 이상한 동작이 있기 때문에 통합 테스트에 반드시 필요한 종류입니다 (삭제 프로그램을 포함한 모든 프로세스에서 파일을 열면 Windows에서 파일 삭제를 허용하지 않는 방식).

TDD 방식은 먼저 통합 테스트작성하는 것입니다. (TDD는 엄밀히 말하면 '단위 테스트'및 '통합 테스트'라는 고유 한 개념이 없으며 테스트 일뿐입니다). 충분할 것입니다. 그래서 일을 끝내고, 멈추고, 집에 가십시오 .

그렇지 않으면 파일을 정리하여 테스트하기가 쉽지 않은 내부 복잡성이 있습니다. 어떤 경우에는 단순히 그 복잡성을 없애고 클래스에 넣은 다음 해당 클래스에 대한 단위 테스트를 작성하십시오 . 데이터베이스, xml 파일 등의 경우에도 공통 클래스를 사용할 수 있음을 알 수 있습니다.

어떤 경우에도 테스트중인 단위가 잘못되었는지 여부를 통과하는 테스트를 작성하기 위해 작성중인 코드의 기본 핵심을 취해이를 '모방'하지는 않을 것입니다.


이 답변은 실제로 나를 위해 관점에 넣었습니다. 'unit test' and 'integration test'; they are just tests.사실적으로는 이것이 내 경우에 가장 좋은 해결책이 될 것이라고 생각합니다. 가장 중요한 경우에 사용중인 파일 시스템 라이브러리를 테스트하고 응용 프로그램이 어떻게 응답 해야하는지 그. 다른 파일 시스템 라이브러리로 전환하면 새 라이브러리와 함께 작동하기 위해 많은 모의 / 테스트 코드를 다시 작성하고 싶지는 않지만 테스트 폴더 구조와 통합 테스트를 사용하면 훨씬 간단 해집니다.
tehDorf

2

귀하의 질문은 "파일 시스템 운영에 의존하는 클래스를 테스트하는 좋은 방법"으로 이해합니다. 나는 당신이 당신의 OS의 파일 시스템을 테스트하고 싶다고 가정하지 않습니다.

@Doc Brown의 답변이 가능한 한 작게 제안 된 것처럼 '파일 시스템 작업에 대한 인터페이스와 "모방" "하려는 노력을 유지하려면 Java 바이너리 스트림 또는 텍스트 리더 (또는 C # 또는 tdd 개발 클래스에서 직접 파일 이름을 가진 파일을 사용하는 대신 사용중인 프로그래밍 언어) .

예:

Java를 사용하여 클래스 CsvReader를 구현했습니다.

public class CsvReader {
    private Reader reader;

    public CsvReader(Reader reader) {
        this.reader = reader;
    }
}

테스트를 위해 다음과 같은 메모리 데이터에 사용했습니다.

String contentOfCsv = "TestColumn1;TestColumn2\n"+
    "value1;value2\n";

CsvReader sut = new CsvReader(java.io.StringReader(contentOfCsv));

또는 테스트 데이터를 리소스에 포함

CsvReader sut = new CsvReader(getClass().getResourceAsStream("/data.csv"));

프로덕션에서는 파일 시스템을 사용합니다.

CsvReader sut = new CsvReader(new BufferedReader( new FileReader( "/import/Prices.csv" ) ));

이 방법으로 내 CsvReader는 파일 시스템에 의존하지 않고 파일 시스템에 대한 구현이있는 추상화 "리더"에 의존합니다.


2
여기서 유일한 문제는 OP가 파일 작업을 말하는 것이 아니라 파일 시스템 작업 및 메타 데이터 작업을 말하고 있다는 것입니다. 디렉터리에있는 모든 파일을 나열하고 모든 그림 파일의 일부 EXIF ​​정보를 업데이트하는 등의 의미를 가진 것 같습니다.
Doc Brown

맞습니다.
Kirbinator

1
String [] List (String directory); 메소드가있는 IDirectoryLister를 작성할 수 있습니다. 그러면 FakeDirectoryLister는 새 String [] { ".", "..", "foo.bat", "bar.exe"}를 반환하여 해당 메소드를 구현할 수 있습니다.
Anders Lindén

0

파일 시스템 조작을위한 랩퍼를 작성하십시오. 테스트에서 랩퍼와 동일한 인터페이스를 구현하는 모형을 전달하십시오. 프로덕션에서는 랩퍼를 전달하십시오.

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