SqueakByExample:7.6: Difference between revisions

From 흡혈양파의 번역工房
Jump to navigation Jump to search
mNo edit summary
(번역수정)
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
==SUnit 프레임웍==
==SUnit 프레임웍==


Sunit은 그림 7.2에 보이는 것 처럼, 4 개의 메인 클래스들인 TestCase, TestSuite, TestResult, 와 TestResource로 구성됩니다. 테스트 리소스의 개념은 셋업을 하기에는 수고가 크지만, 전체 테스트 시리즈들에 의해 사용될 수 있는 리소스를 나타내기 위해 SUnit 3.1에 소개되었습니다.
SUnit은 4개의 메인클레스로 구성되어 있습니다: TestCase, TestSuite, TestResult, TestResource 인데 그림 7.2 에서 확인할 수 있습니다. 테스트 리소스의 개념은 구성하는데 많은 비용이 들기는 하지만 테스트의 시리즈에 리소스로 사용되기 위해 SUnite 3.1부터 등장했습니다. TestResource 는 테스트들의 suite 이전에 한번만 실행되는 setUp 메서드를 명시합니다; TestResource는 각 테스트 전에 실행되는 TestCase>>setUp 에 대해서 고유합니다.


TestResource는 테스트들의 슈트 전에 단 한번 실행되는 setUp 메서드를 지정하며 이것은 각 테스트 전에 실행되는 TestCase»setUp 메서드에만 특별히 고유한 작업입니다.
[[image:sunit-classes.png|none|800px|thumb|그림 7.2: SUnit 의 핵심이 되는 4개의 클래스]]




[[image:sunit-classes.png|none|895px|thumb|그림 7.2: SUnit의 핵심(core)을 나타내는 4개의 클래스]]


===TestCase===


===TestCase===
TestCase 는 하위 클래스가 되도록 설계된 임의의 클래스 이며 그 하위 클래스들 각각은 공통된 컨텍스트(테스트 suite)를 공유하는 테스트들의 그룹을 나타냅니다. 각 테스트는 TestCase, 실행중인 setup, 실행중인 테스트 메서드 자체, 그리고 실행중인 tearDown의 하위 클래스의 새로운 인스턴스를 만들어서 실행됩니다.
 
컨텍스트는 하위 클래스의 인스턴스 변수들과 메서드 setUp 의 특화로 지정되며, 이러한 컨텍스트의 지정 동작은 인스턴스 변수들을 초기화합니다. TestCase 의 하위 클래스들은 tearDown 메서드를 재지정할 수 있으며, 이러한 재지정작업은 각 테스트의 실행 후에 호출되고, setUp 을 실행하는 동안 모든 할당된 객체들을 릴리즈 하기 위해 사용될 수 있습니다.


TestCase는 서브클래스가 되도록 디자인된 임의의 클래스 이며 그 서브클래스들의 각각은 공통된 컨텍스트(그것은 test suite임)를 공유하는 테스트들의 그룹을 나타냅니다. 각 테스트는 TestCase, 실행중인 setup, 실행중인 테스트 메서드 자체, 그리고 실행중인 tearDown의 서브클래스의 새로운 인스턴스를 만들어 실행됩니다.


컨텍스트는 서브클래스의 인스턴스 변수들과 메서드 setUp의 특수화(specialization)에 의해 지정되며, 이 지정은 인스턴스 변수들을 초기화합니다. TestCase의 서브클래스들은 메서드 tearDown을 재지정(override)할 수 있으며, 이것은 각 테스트의 실행 후에 호출되고, 그리고 setUp을 실행하는 동안 모든 할당된 객체들을 릴리즈 하기 위해 사용될 수 있습니다.


===TestSuite===
===TestSuite===


클래스 TestSuite의 인스턴스들은 test cases의 컬렉션(collection)을 포함합니다. TestSuite의 인스턴스는 테스트들과 다른 테스트 슈트들(suites)을 담고 있습니다. 개별적 TestCases와 TestSuites는 동일한 프로토콜(protocol)을 이해하므로, 동일한 방식으로 취급될 수 있습니다. 예를 들면 둘 다 모두 실행될 수 있습니다. 이것은 사실, TestSuite가 합성이고(composite) TestCase가 leaves인 위치에 있는 합성 패턴(composite pattern)의 어플리케이션입니다- 이 패턴 2에 대한 좀 더 많은 정보를 보시려면 Design Patterns를 보십시오.<ref name="주석7-2">Erich Gamma et al., Design Patterns: Elements of Reusable Object-Oriented Software. Reading, Mass.: Addison Wesley, 1995, ISBN 0–201–63361–2–(3).</ref>
TestSuite 클래스의 인스턴스들은 test cases 의 컬렉션을 포함합니다. TestSuite 의 인스턴스는 테스트들과 다른 테스트 suite 를 포함하고 있습니다. 즉 테스트 suite는 TestCase 와 TestSuite 의 하위인스턴스를 포함하고 있다는게 됩니다. 각각의 TestCases 와 TestSuites 는 같은 프로토콜을 알아들을 수 있기때문에, 같은방식으로 취급하는것도 가능합니다; 예를 들면 양쪽다 실행이 가능하다는 것이죠. 사실 이런것들이 가능한 이유는, TestSuite 는 TestCases 의 일부와 합성을 통한 composite 패턴의 어플리케이션이기 때문입니다.- composite 패턴에 대한 좀 더 많은 정보를 보시려면 Design Patterns<ref name="주석7-2">Erich Gamma et al., Design Patterns: Elements of Reusable Object-Oriented Software. Reading, Mass.: Addison Wesley, 1995, ISBN 0–201–63361–2–(3).</ref> 를 봐주시기 바랍니다.
 
 


===TestResult===
===TestResult===


클래스 TestResult는 TestSuite 실행의 결과를 나타냅니다. 이 클래스는 패스된 테스트들의 개수, 실패된 테스트들의 개수 그리고 발생한 에러들의 개수를 기록합니다.
TestResult 클래스는 TestSuite 실행의 결과를 나타냅니다. 이 클래스는 통과한 테스트들의 개수, 실패한 테스트들의 개수 그리고 발생한 오류의 갯수등을 기록합니다.
 
 


===TestResource===
===TestResource===


테스트들의 슈트(suite)의 중요한 특징들 중의 하나는 테스트들은 각각 독립적이 되어야만 한다는 것입니다: 한 개의 테스트의 실패는 그 테스트에 기초하여 다른 테스트들이 대량으로 실패되는 현상을 야기시키면 안되며, 또한 테스트들의 실행 순서에 영향을 미쳐서도 안됩니다. 각 테스트 전과 teardown 후에 setUp을 수행하면 이 독립성 강화를 돕습니다.
테스트 suite 의 중요한 특징 중 하나는 테스트는 각각 독립적이어야 한다는 점입니다: 한 개의 테스트의 실패때문에 다른 테스트들이 대량으로 실패되는 현상이 일어나서는 안되며, 또한 테스트들은 서로의 실행 순서에 영향을 미쳐서도 안됩니다. 각 테스트를 진행하기전에 setUp 을 사용하거나 테스트뒤에 tearDown 을 쓰는건 테스트사이의 독립성을 강화하는데 도움이 됩니다.
 
그럼에도 불구하고 필요한 컨텍스트를 셋업하는 작업이 너무나 시간을 소모하여서 각 테스트 실행 전에 한번에 실용적으로 셋업이 되게 하지 못하는 사례들이 생깁니다. 더욱이, 만약 testcases 가 테스트들에 의해 사용된 리소스들에 지장을 주지 않는 다는 사실이 알려졌다면, 각 테스트를 위해 그것들을 새롭게 설정하는 작업은 시간 낭비이며, 테스트의 슈트를 위해 한번만 셋업을 하는 것으로 충분합니다. 예컨데, 테스트들의 슈트가 데이터 베이스를 조회(query)할 필요가 있거나 몇몇 컴파일된 코드에 대한 분석을 시행해야 할 필요가 있다고 가정해 보십시오. 그러한 경우에는, 실행할 모든 테스트를 시작하기 전에 데이터 베이스를 셋업하고, 그것에 대한 연결(connection)을 열거나 또는 몇몇 소스 코드를 컴파일하는 작업이 좋은 실행법입니다.


우리는 어디에서 이러한 리소스들을 캐쉬하여서, 테스트의 슈트에 의해 공유되도록 할 수 있을까요? 특정 TestCase subintance의 인스턴스는 할 수 없습니다. 그 이유는 이러한 인수는 단일 테스트 동안만 지속되기 때문입니다. 글로벌 변수는 작동할 것이지만, 너무나 많은 글로벌 변수들을 사용하는 것은 이름공간(the name space)을 오염시킬 것이며, 글로벌 변수들과 테스트들 사이를 묶는 것은 양함수가 되지 않을 것(혹은 명시 되지 않을 것, 원문 explicit은 수학에서는 양함수 일반적으로 명백, 명시의 뜻을 가집니다:역주)에 기초합니다. 더 나은 해결책은 필요한 리소스를 몇몇 클래스들의 단일 객체에 집어 넣는 것입니다. 클래스 TestResouorce는 이러한 리소스 클래스들에 의해 하위 분류 되기 위해(subclassed) 존재합니다. 각 TestResource의 서브클래스는 현재 메시지를 이해하며, 그 이해를 바탕으로 그 서브클래스의 단일 인스턴스로 답할 것입니다. 메서드 setUp과 tearDown은 반드시 리소스가 초기화 되고 최종화(finalized) 되도록 하기 위해 서브클래스 내부에서 재정의(overridden)되어야만 합니다.  
하지만, 가끔 테스트를 실행하기전 한번 유용하게 사용되어야 하는데 필요한 컨텍스트를 설정하는 작업이 너무나 시간을 잡아먹어서 사용하기 힘든때가 있죠. 더군다나, 이런 테스트 케이스가 테스트에서 사용하는 리소스에 지장을 주지않는다는것을 알게된다면 각각의 테스트를 위해 컨텍스트를 다시 설정하는 작업은 시간낭비입니다; 이런경우 테스트의 각 suite 는 한번만 설정하는것으로 충분합니다. 예컨데, 테스트들의 suite 가 데이터 베이스를 조회할 필요가 있거나 몇몇 컴파일한 코드에 대한 분석을 시행해야 할 필요가 있다고 가정해 보도록 합니다. 이런경우, 실행할 모든 테스트를 시작하기 전에 데이터 베이스를 먼저 설정하고, 데이터베이스에 대한 연결을 열거나 또는 몇몇 소스 코드를 컴파일하는 작업이 좋은 실행법입니다.


한 가지 남은 것: SUnit은 어떤 테스트 슈트(test suite)와 어떤 리소스가 연관되었는지에 관해 어느 정도는 들어야만 합니다. 리소스는 클래스 메서드 리소스를 재정의(override)함으로써 Testcase의 특정 서브클래스와 연관됩니다. TestSuite의 리소스는 디폴트로 그것이 포함하고 있는 TestCases의 리소스의 연합(union)입니다.
대체 어디로 이러한 자원을 캐쉬해야, 테스트 suite 들이 공유할 수 있을까요? 특정 인스턴스 변수는 TestCase 의 하위인스턴스가 될 수 없는데, 왜냐하면 이런 인스턴스(변수)는 오직 테스트를 진행하는 과정에서만 존재되기 때문입니다. 글로벌 변수라면 항상 존재하기때문에 리소스의 용도로 사용이 가능합니다만, 많이 쓰는경우 namespace 가 복잡해지며, 글로벌 변수와 테스트사이의 의존성의 강제되는것도, 별도로 명시되는것도 아니기때문에 클로벌변수의 리소스 사용은 권장할만한 방법은 아닙니다. 보다 좋은 방법이 있는데, 필요한 리소스를 몇몇 클래스들의 singleton 오브젝트에 집어 넣는 거죠. 이런 경우에 사용하기 위해 리소스클래스로 TestResource 클래스가 준비되어있습니다. TestResource 의 하위 클래스로 생성된 singletone 인스턴스에 대해 current 메시지를 사용할 수 있으며, current 메세지 사용시 해당되는 singleont 인스턴스가 응답하게 됩니다. 반드시 테스트의 리소스가 생성 되고 소멸되도록 하기 위해 setUp 메서드와 tearDown 메서드는 하위 클래스 내부에서 재정의되어야 합니다.


여기에 예시가 있습니다. 우리는 MyTestResource라 불리는 TestResource의 서브클래스를 정의하고 그리고, 우리는 그것이 사용할 테스트 클래스들의 배열(array)을 리턴하기 위해 클래스 메서드 리소스를 특화(specializing)함으로써 MyTestCase와 MyTestRecource를 조합시킬 것입니다.  
한가지더: SUnit 은 어떤 테스트 suite 와 어떤 리소스가 연관되었는지에 관해 어느 정도는 알고 있어야만 합니다. 리소스는 클래스 메서드 리소스를 재정의함으로써 TestCase 의 특정 하위 클래스와 연관됩니다. TestSuite 의 리소스는 기본적으로 그것이 포함하고 있는 TestCases 의 리소스와 묶여집니다.


예제를 보도록 하겠습니다. TestResource 의 하위 클래스로서 MyTestResource 를 정의하고, MyTestCase 의 클래스 메소드인 resources 를 오버라이드 해서 미리 생성한 리소스인 MyTestResource 의 배열이 반환되도록 합니다.


클래스 7.9: TestResource 서브클래스의 예


클래스 7.9: TestResource 하위 클래스의 예
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
TestResource subclass: #MyTestResource
TestResource subclass: #MyTestResource
   instanceVariableNames: ''
   instanceVariableNames: ''
  MyTestCase class»resources
 
MyTestCase class>>resources
   "associate the resource with this class of test cases"
   "associate the resource with this class of test cases"
   ↑{ MyTestResource }
   ↑{ MyTestResource }

Revision as of 02:59, 22 March 2013

SUnit 프레임웍

SUnit은 4개의 메인클레스로 구성되어 있습니다: TestCase, TestSuite, TestResult, TestResource 인데 그림 7.2 에서 확인할 수 있습니다. 테스트 리소스의 개념은 구성하는데 많은 비용이 들기는 하지만 테스트의 시리즈에 리소스로 사용되기 위해 SUnite 3.1부터 등장했습니다. TestResource 는 테스트들의 suite 이전에 한번만 실행되는 setUp 메서드를 명시합니다; TestResource는 각 테스트 전에 실행되는 TestCase>>setUp 에 대해서 고유합니다.

그림 7.2: SUnit 의 핵심이 되는 4개의 클래스


TestCase

TestCase 는 하위 클래스가 되도록 설계된 임의의 클래스 이며 그 하위 클래스들 각각은 공통된 컨텍스트(테스트 suite)를 공유하는 테스트들의 그룹을 나타냅니다. 각 테스트는 TestCase, 실행중인 setup, 실행중인 테스트 메서드 자체, 그리고 실행중인 tearDown의 하위 클래스의 새로운 인스턴스를 만들어서 실행됩니다.

컨텍스트는 하위 클래스의 인스턴스 변수들과 메서드 setUp 의 특화로 지정되며, 이러한 컨텍스트의 지정 동작은 인스턴스 변수들을 초기화합니다. TestCase 의 하위 클래스들은 tearDown 메서드를 재지정할 수 있으며, 이러한 재지정작업은 각 테스트의 실행 후에 호출되고, setUp 을 실행하는 동안 모든 할당된 객체들을 릴리즈 하기 위해 사용될 수 있습니다.


TestSuite

TestSuite 클래스의 인스턴스들은 test cases 의 컬렉션을 포함합니다. TestSuite 의 인스턴스는 테스트들과 다른 테스트 suite 를 포함하고 있습니다. 즉 테스트 suite는 TestCase 와 TestSuite 의 하위인스턴스를 포함하고 있다는게 됩니다. 각각의 TestCases 와 TestSuites 는 같은 프로토콜을 알아들을 수 있기때문에, 같은방식으로 취급하는것도 가능합니다; 예를 들면 양쪽다 실행이 가능하다는 것이죠. 사실 이런것들이 가능한 이유는, TestSuite 는 TestCases 의 일부와 합성을 통한 composite 패턴의 어플리케이션이기 때문입니다.- composite 패턴에 대한 좀 더 많은 정보를 보시려면 Design Patterns[1] 를 봐주시기 바랍니다.


TestResult

TestResult 클래스는 TestSuite 실행의 결과를 나타냅니다. 이 클래스는 통과한 테스트들의 개수, 실패한 테스트들의 개수 그리고 발생한 오류의 갯수등을 기록합니다.


TestResource

테스트 suite 의 중요한 특징 중 하나는 테스트는 각각 독립적이어야 한다는 점입니다: 한 개의 테스트의 실패때문에 다른 테스트들이 대량으로 실패되는 현상이 일어나서는 안되며, 또한 테스트들은 서로의 실행 순서에 영향을 미쳐서도 안됩니다. 각 테스트를 진행하기전에 setUp 을 사용하거나 테스트뒤에 tearDown 을 쓰는건 각 테스트사이의 독립성을 강화하는데 도움이 됩니다.

하지만, 가끔 테스트를 실행하기전 한번 유용하게 사용되어야 하는데 필요한 컨텍스트를 설정하는 작업이 너무나 시간을 잡아먹어서 사용하기 힘든때가 있죠. 더군다나, 이런 테스트 케이스가 테스트에서 사용하는 리소스에 지장을 주지않는다는것을 알게된다면 각각의 테스트를 위해 컨텍스트를 다시 설정하는 작업은 시간낭비입니다; 이런경우 테스트의 각 suite 는 한번만 설정하는것으로 충분합니다. 예컨데, 테스트들의 suite 가 데이터 베이스를 조회할 필요가 있거나 몇몇 컴파일한 코드에 대한 분석을 시행해야 할 필요가 있다고 가정해 보도록 합니다. 이런경우, 실행할 모든 테스트를 시작하기 전에 데이터 베이스를 먼저 설정하고, 데이터베이스에 대한 연결을 열거나 또는 몇몇 소스 코드를 컴파일하는 작업이 좋은 실행법입니다.

대체 어디로 이러한 자원을 캐쉬해야, 테스트 suite 들이 공유할 수 있을까요? 특정 인스턴스 변수는 TestCase 의 하위인스턴스가 될 수 없는데, 왜냐하면 이런 인스턴스(변수)는 오직 테스트를 진행하는 과정에서만 존재되기 때문입니다. 글로벌 변수라면 항상 존재하기때문에 리소스의 용도로 사용이 가능합니다만, 많이 쓰는경우 namespace 가 복잡해지며, 글로벌 변수와 테스트사이의 의존성의 강제되는것도, 별도로 명시되는것도 아니기때문에 클로벌변수의 리소스 사용은 권장할만한 방법은 아닙니다. 보다 좋은 방법이 있는데, 필요한 리소스를 몇몇 클래스들의 singleton 오브젝트에 집어 넣는 거죠. 이런 경우에 사용하기 위해 리소스클래스로 TestResource 클래스가 준비되어있습니다. TestResource 의 하위 클래스로 생성된 singletone 인스턴스에 대해 current 메시지를 사용할 수 있으며, current 메세지 사용시 해당되는 singleont 인스턴스가 응답하게 됩니다. 반드시 테스트의 리소스가 생성 되고 소멸되도록 하기 위해 setUp 메서드와 tearDown 메서드는 하위 클래스 내부에서 재정의되어야 합니다.

한가지더: SUnit 은 어떤 테스트 suite 와 어떤 리소스가 연관되었는지에 관해 어느 정도는 알고 있어야만 합니다. 리소스는 클래스 메서드 리소스를 재정의함으로써 TestCase 의 특정 하위 클래스와 연관됩니다. TestSuite 의 리소스는 기본적으로 그것이 포함하고 있는 TestCases 의 리소스와 묶여집니다.

예제를 보도록 하겠습니다. TestResource 의 하위 클래스로서 MyTestResource 를 정의하고, MyTestCase 의 클래스 메소드인 resources 를 오버라이드 해서 미리 생성한 리소스인 MyTestResource 의 배열이 반환되도록 합니다.


클래스 7.9: TestResource 하위 클래스의 예

TestResource subclass: #MyTestResource
  instanceVariableNames: ''

MyTestCase class>>resources
  "associate the resource with this class of test cases"
  { MyTestResource }


Notes

  1. Erich Gamma et al., Design Patterns: Elements of Reusable Object-Oriented Software. Reading, Mass.: Addison Wesley, 1995, ISBN 0–201–63361–2–(3).