작성자: yagur Rev : 3
프레임워크 러프 스케치
동기, 주기, 새로운 프레임워크 디자인, 복잡도, 엔트로피, 그리고 함정에 관한것들이 이전 내용이었다. 이는 새로운 프레임워크 구성을 구상하고 구체화하기 전에 고려해야할 사항들이다. 많은 것을 고려할수 밖에 없는 이유는 프레임워크가 작성할 테스트에 사용될때 그 결합도가 높기때문이다(테스트가 프레임워크에 기반을 두고 있는점을 생각해보면 된다). 결합도가 높으면 변경의 영향력이 크다.
프레임워크는 OCP(Open Close Principle)를 잊지 말아야한다. 일단 작성된 프레임워크는 다른 소프트웨어의 테스트에 사용되기 때문에 변경이 있을경우, 자칫 다른 테스트를 전부 변경해야하는 상황이 생기기 때문이다. 하지만 OCP때문에 프레임워크의 진화를 망설여서는 안된다, 새로운 개념을 도입하고 그에 합당한 디자인 변경이 생긴다면 해야한다. OCP는 한가지의 원칙일뿐, 도약을 방해해선 안된다. 원칙과 도약중 어느것의 가치가 큰지는 사용자가 판단할 몫이다. 하지만 원칙을 지키려 노력한 디자인는 진화의 비용을 줄여줄것이다.
우회방법도 존재 한다. 그중 하나는 JUnit과 같이 메이저 버전을 두어 분리 시킬수 있다. 그들은 테스트 프로젝트를 만들때 JUnit3, 4를 선택할수 있게 만들어 놓았다. 하지만 이것은 근본적인 해결책은아니다.
우리가 사용할 테스트 프레임워크가 필요로 하는 명세가 항상 같을것이면 행복할것이다. 그러나 소프트웨어는 계속 변화하는 성질을 가지고 있으며 테스트를 위한 명세는 변하게 될것이다. 명세와 계획은 바뀔것이고 프레임워크의 진화를 막긴 힘들다.
스케치는 구체적인것을 실행하기전에 도움이 된다. 그림을 그릴때도 마찬가지이고, 프로그램을 작성할때도 마찬가지이다.
지금 제작해 사용중인 테스트 프레임워크의 배치 다이어그램Deployment Diagram이며 단순 참고용으로 보면 된다. 사용자는 정의된 한가지의 프레임워크에만 의존하며 되며 그들은 사용 목적에 따라 각자의 컴포넌트를 동적 로드하고 사용하게 된다.
테스트 프레임워크, 컴포넌트 설계(Component Design of Test Framework)
뷰를 실시간 뷰와 정적 뷰로 나누었다. 이유는 상황에 따라 필요 컴포넌트가 다르기 때문이다. 테스트 주도 개발(TDD)을 하며 실시간 뷰를 요구할수도 있고, 자동화된 연속 통합continuous integration을 위해 단순 리포트만이 필요할수도 있기때문이다. 혹은 실시간 뷰로 보며, 테스트가 끝나면 리포트를 웹싸이트에 올리기를 바랄수도 있다. 필요에 의해 컴포넌트를 사용하면 되며 이는 사용자가 의존하는 TestFramework 컴포넌트에서 처리하면 된다.
테스트 모델 설계(Model of Test Framework)
실제로 사용하고 있는 모델이며, 단순 사례로 참고하길 바란다. 프레임워크 사용자는 자세히 몰라도 되거나 Factory나 몇몇 매크로에 의존하게 된다. 다중 상속이 싫거나, 언어에서 지원이 되지 않는다면 위임Delegation을 활용하면 된다. TestNode에서 수많은 노드 타입들로 확장을 하고 있는것이 싫다면, 속성을 활용하도록 디자인을 변경할수 있다.
위의 디자인은 테스트 노드가 하위 Node 혹은 Leaf, 그리고 Depedency를 연결을 할때 상세한 정책Policy을 두기를 원해서이다. 정책 결정을 다른 객체에 위임하기위한 Proxy로서 확장Extend을 하였다.(여기서 정책의 예로 한가지 들어보자면 Class Test의 하위 테스트로 System Test가 될수 없는것과 같은것이다.)
TestSuite와 TestObject는 상속과 집합 환계로 이루어져 있는데 이것은 Composite Pattern이고 TestObject는 Observable이며 View 컴포넌트 객체들은 Observer가 될것이다.
부트 스트랩 (Boot Strap)
부트 스트래핑은 스스로 자기의 신발끈을 당겨서 자신을 공중에 띄워야 하는 것과 같은 모순적 상황을 일컫는다. 바퀴를 재발명해 기능을 추가하여 사용하려면 대상의 테스트가 필요하다. 테스트를 하기위한 프레임워크를 테스트하라니? 좀 모순된 상황처럼 받아들일수 있다. 일종의 자기 참조Self Referencial 프로그래밍이 될수 있는데, 이럴때는 구조적인것이 아니며 가장 단순한 형태인 함수만 활용하는것도 하나의 방법이다. 각 객체 단위별 검증을 위한 함수를 작성하여 실행하면 일정 부분 검증이 된다. 이런 형태로 커버리지를 전체로 늘려 나가면 된다. 복잡한 구조를 띌 필요가 없는 장점이 있이 있으나, 절차적Procedural이기 때문에 실행 순서를 수동적으로 고민해야한다.
다른 방법으로는 가장 간단한 테스트 프레임워크로부터 시작해 다음 세대 프레임워크를 검증하면된다. 이것은 마치 컴파일러 작성을 위해 이전 세대의 컴파일러를 활용하는것과 같다. 그리고 다음 세대 컴파일러는 이전 세대의 컴파일러로 작성된다. 그리고 이들은 계속 이전 세대의 것을 활용해 다음 세대의 것으로 진화할것이다.
테스트 프레임워크도 같은 원리로 진화할수 있다.
프레임워크 러프 스케치
동기, 주기, 새로운 프레임워크 디자인, 복잡도, 엔트로피, 그리고 함정에 관한것들이 이전 내용이었다. 이는 새로운 프레임워크 구성을 구상하고 구체화하기 전에 고려해야할 사항들이다. 많은 것을 고려할수 밖에 없는 이유는 프레임워크가 작성할 테스트에 사용될때 그 결합도가 높기때문이다(테스트가 프레임워크에 기반을 두고 있는점을 생각해보면 된다). 결합도가 높으면 변경의 영향력이 크다.
프레임워크는 OCP(Open Close Principle)를 잊지 말아야한다. 일단 작성된 프레임워크는 다른 소프트웨어의 테스트에 사용되기 때문에 변경이 있을경우, 자칫 다른 테스트를 전부 변경해야하는 상황이 생기기 때문이다. 하지만 OCP때문에 프레임워크의 진화를 망설여서는 안된다, 새로운 개념을 도입하고 그에 합당한 디자인 변경이 생긴다면 해야한다. OCP는 한가지의 원칙일뿐, 도약을 방해해선 안된다. 원칙과 도약중 어느것의 가치가 큰지는 사용자가 판단할 몫이다. 하지만 원칙을 지키려 노력한 디자인는 진화의 비용을 줄여줄것이다.
우회방법도 존재 한다. 그중 하나는 JUnit과 같이 메이저 버전을 두어 분리 시킬수 있다. 그들은 테스트 프로젝트를 만들때 JUnit3, 4를 선택할수 있게 만들어 놓았다. 하지만 이것은 근본적인 해결책은아니다.
적을 만나면 계획은 바뀐다 - 헬무트 폰 몰트케
우리가 사용할 테스트 프레임워크가 필요로 하는 명세가 항상 같을것이면 행복할것이다. 그러나 소프트웨어는 계속 변화하는 성질을 가지고 있으며 테스트를 위한 명세는 변하게 될것이다. 명세와 계획은 바뀔것이고 프레임워크의 진화를 막긴 힘들다.
스케치는 구체적인것을 실행하기전에 도움이 된다. 그림을 그릴때도 마찬가지이고, 프로그램을 작성할때도 마찬가지이다.
지금 제작해 사용중인 테스트 프레임워크의 배치 다이어그램Deployment Diagram이며 단순 참고용으로 보면 된다. 사용자는 정의된 한가지의 프레임워크에만 의존하며 되며 그들은 사용 목적에 따라 각자의 컴포넌트를 동적 로드하고 사용하게 된다.
테스트 프레임워크, 컴포넌트 설계(Component Design of Test Framework)
뷰를 실시간 뷰와 정적 뷰로 나누었다. 이유는 상황에 따라 필요 컴포넌트가 다르기 때문이다. 테스트 주도 개발(TDD)을 하며 실시간 뷰를 요구할수도 있고, 자동화된 연속 통합continuous integration을 위해 단순 리포트만이 필요할수도 있기때문이다. 혹은 실시간 뷰로 보며, 테스트가 끝나면 리포트를 웹싸이트에 올리기를 바랄수도 있다. 필요에 의해 컴포넌트를 사용하면 되며 이는 사용자가 의존하는 TestFramework 컴포넌트에서 처리하면 된다.
테스트 모델 설계(Model of Test Framework)
실제로 사용하고 있는 모델이며, 단순 사례로 참고하길 바란다. 프레임워크 사용자는 자세히 몰라도 되거나 Factory나 몇몇 매크로에 의존하게 된다. 다중 상속이 싫거나, 언어에서 지원이 되지 않는다면 위임Delegation을 활용하면 된다. TestNode에서 수많은 노드 타입들로 확장을 하고 있는것이 싫다면, 속성을 활용하도록 디자인을 변경할수 있다.
위의 디자인은 테스트 노드가 하위 Node 혹은 Leaf, 그리고 Depedency를 연결을 할때 상세한 정책Policy을 두기를 원해서이다. 정책 결정을 다른 객체에 위임하기위한 Proxy로서 확장Extend을 하였다.(여기서 정책의 예로 한가지 들어보자면 Class Test의 하위 테스트로 System Test가 될수 없는것과 같은것이다.)
TestSuite와 TestObject는 상속과 집합 환계로 이루어져 있는데 이것은 Composite Pattern이고 TestObject는 Observable이며 View 컴포넌트 객체들은 Observer가 될것이다.
부트 스트랩 (Boot Strap)
부트 스트래핑은 스스로 자기의 신발끈을 당겨서 자신을 공중에 띄워야 하는 것과 같은 모순적 상황을 일컫는다. 바퀴를 재발명해 기능을 추가하여 사용하려면 대상의 테스트가 필요하다. 테스트를 하기위한 프레임워크를 테스트하라니? 좀 모순된 상황처럼 받아들일수 있다. 일종의 자기 참조Self Referencial 프로그래밍이 될수 있는데, 이럴때는 구조적인것이 아니며 가장 단순한 형태인 함수만 활용하는것도 하나의 방법이다. 각 객체 단위별 검증을 위한 함수를 작성하여 실행하면 일정 부분 검증이 된다. 이런 형태로 커버리지를 전체로 늘려 나가면 된다. 복잡한 구조를 띌 필요가 없는 장점이 있이 있으나, 절차적Procedural이기 때문에 실행 순서를 수동적으로 고민해야한다.
다른 방법으로는 가장 간단한 테스트 프레임워크로부터 시작해 다음 세대 프레임워크를 검증하면된다. 이것은 마치 컴파일러 작성을 위해 이전 세대의 컴파일러를 활용하는것과 같다. 그리고 다음 세대 컴파일러는 이전 세대의 컴파일러로 작성된다. 그리고 이들은 계속 이전 세대의 것을 활용해 다음 세대의 것으로 진화할것이다.
테스트 프레임워크도 같은 원리로 진화할수 있다.
'개발 > 수필' 카테고리의 다른 글
| 테스트와 장인 - 8 (0) | 2008/03/19 |
|---|---|
| 객체 지향 소프트웨어 일주 - 2 (2) | 2008/03/15 |
| 테스트와 장인 - 7 (0) | 2008/03/12 |
| 객체 지향 소프트웨어 일주 - 1 (0) | 2008/03/11 |
| 테스트와 장인 - 6 (2) | 2008/02/25 |
| 테스트와 장인 - 5 (0) | 2008/02/22 |





Recent Comment