Creative Commons License

Microsoft .NET

닷넷!시작하기
닷넷! Ver 2.0~
닷넷!스킬업
웹개발
윈폼개발
실용모듈개발
Tip & Tech
하루 한 문법

Microsoft .NET 개발자들을 위한 공간입니다. 기초강의에서 부터 고급 기술 정보 및 팁등을 다루도록 하겠습니다.

.

닷넷!스킬업

닷넷 기술을 조금 더 깊이 다루고자 합니다. 특정 주제를 정하지 않고 이슈 발생 시 마다 체계적으로 정리하여 공유하겠습니다. 이전 자료를 옮겨온 곳이기도 합니다.

[Attribute] - 사용자정의 Attribute (TestCaseAttribute)

작성자 : 박종명
최초 작성일 : 2008-05-30 (금요일)
최종 수정일 : 2008-05-30 (금요일)
조회 수 : 2340

이번에는 어트리뷰트의 마지막 글로써 유용한 예제를 하나 살펴 보자.
Wrox 사의 비기닝 C# 이라는 책의 예제이다.
 
간단하고 쉬운 예제이지만 사용자 정의 어트리뷰트 사용성에 대해 생각하게 만들어 주는 예제인 듯 하여 게재하도록 하겠다.
 
일단, 데모의 시나리오는 다음과 같다.

일반적으로 클래스를 만들면 특정 메서드를 임의로 테스트를 하게 된다. 이를 보통 유닛테스트라 하는데 이 과정을 어트리뷰트를 정의해서 수행토록 한다. 정의한 어트리뷰트는 실제 테스트를 수행하는 클래스의 타입을 전달받아 그 타입의 인스턴스를 생성함으로써 그 타입의 생성자를 호출하게 된다.

결국 이 생성자에는 테스트 대상 클래스의 임의의 메서드를 호출 함으로써 유닛 테스트를 수행하게 된다. 
테스트 대상 클래스와 테스트 수행 클래스를 정의(이 클래스의 생성자에서 테스트 수행하도록)하여 어트리뷰트에게 전달해 주면 유닛 테스트가 가능토록 하는 것이다.
 

* 참여 클래스 설명
1) 테스트 대상 클래스 : Unit
2) 테스트 수행 클래스 : TestAnObject
                                
(이 클래스의 생성자는 Unit 클래스의 임의의 메소드를 테스트하는 코드가 있어야 한다)
3) 어트리뷰트 : TestCaseAttribute
 
 
* 프로그램 흐름도

객체들의 흐름을 간단하게 도식화 해 보자.



1. Unit 클래스는 테스트 대상 클래스로써 자신을 테스트 할 클래스(TestAnObject) 의 타입을 어트리뷰트에게 전달
   한다

2. Main 프로그램에서는 현재 어셈블리안의 타입중에 TestCaseAttriubte 가 선언된 타입을 찾아 그 어트리뷰트의
   Test 메서드를 호출한다

3. TestCaseAttribute 객체의 Test 메서드는 전달받은 TestAnObject 타입의 인스턴스를 생성한다.
    당연히 이 때 TestAnObject  의 생성자가 호출된다(이 생성자에는 실제 테스트 코드가 있다)

4. TestCaseAttribute 객체의 생성자에서는 Unit 객체의 임의의 메서드를 호출하여 원하는 값이 아닐 경우
    Exception을 강제로 일으킨다.
 


* 소스 코드

1. 테스트 대상 클래스 (Unit)

[TestCase(typeof(TestAnObject))]

         public class Unit

         {

                  public Unit(){}

                  public int Do()

                  {

                           return 9;

                  }

         }

 
2. 실제 테스트 수행 클래스(TestAnObject)

public class TestAnObject

         {

                  //이 클래스의 생성자가 호출되면 테스트 대상 클래스를 테스트 한다

                  //업무규칙 : 클래스의 생성자에서 유닛테스트를 수행하라

                  public TestAnObject()

                  {

                           Unit u = new Unit();

 

                           if(u.Do() != 999)

                                   throw new Exception("Pesky Kids");

                  }

         }

 
3. 사용자 정의 어트리뷰트

[AttributeUsage(AttributeTargets.Class,AllowMultiple=false,Inherited=true)]

         public class TestCaseAttribute : System.Attribute

         {

                  public readonly System.Type TestCase;

 

                  public TestCaseAttribute(System.Type testCase)

                  {

                           this.TestCase = testCase; 

                  }                

 

                  public void Test()

                  {

                           //테스트 수행하기 위해 테스트를 수행할 클래스의 인스턴스를 만든다

                           //이 인스턴스의 생성자에서 실제 테스트를 수행한다

                           object o = Activator.CreateInstance(TestCase);

                  }

         }

 
4. 메인 프로그램

class UnitTest

         {                

                  [STAThread]

                  static void Main(string[] args)

                  {

                           //현재의 응용프로그램 도메인에 있는 실행파일(어셈블리)을 가져온다
                            (TestCaseAttributeDemo.exe)

                           Assembly a = Assembly.GetEntryAssembly();

 

                           //어셈블리 안의 형식들을 검사한다                   

                           System.Type[] types = a.GetExportedTypes();

 

                           foreach(System.Type t in types)

                           {

                                   Console.WriteLine("검색된 형식 : {0}",t.ToString());

 

                                   //이 형식에 TestCaseAttribute 라는 사용자 정의 어트리뷰트가
                                   //선언되어 있는지 검사.

                                   object[] atts = 
                                      t.GetCustomAttributes(typeof(TestCaseAttribute),false);

 

                                   //만일 이 형식에 TestCaseAttribute 어트리뷰트가 선언되어 있다면..

                                   if(1 == atts.Length)

                                   {

                                            Console.WriteLine(" TestCaseAttribute 가 다음 형식에
                                                    선언되어 있음 {0}",t.ToString());

                                           

                                            //검색된 어트리뷰트(object 타입) TestCaseAttribute
                                            //캐스팅 함

                                             TestCaseAttribute tca = atts[0] as TestCaseAttribute;

 

                                            try

                                            {

                                                     tca.Test(); //테스트 수행

                                                     Console.WriteLine("  테스트 성공");

                                            }

                                            catch(Exception ex)

                                            {

                                                     Console.WriteLine("  테스트 실패, 실패 사유
                                                                    {0}",ex.Message)                          

                                            }

                                   }

                           }

                  }                

         }

 

이름
비밀번호
홈페이지
HC <- 왼쪽의 문자를 오른쪽 박스에 똑같이 입력해 주세요