.net reflection

풀그림 2009. 3. 19. 17:51

. 포함관계

다음과 같이 Assemblies안에 포함관계가 있다.

Assemblies> Modules> types> members

 

예제

// Gets the mscorlib assembly in which the object is defined.

Assembly a = typeof(Object).Module.Assembly;

 

// Loads an assembly using its file name.

Assembly a = Assembly.LoadFrom ("MyExe.exe");

// Gets the type names from the assembly.

Type [] types2 = a.GetTypes ();

foreach (Type t in types2)

{

    Console.WriteLine (t.FullName);

}

 

// This program lists all the public constructors

// of the System.String class.

using System;

using System.Reflection;

class ListMembers {

    public static void Main(String[] args) {

        Type t = typeof(System.String);

        Console.WriteLine ("Listing all the public constructors of the {0} type", t);

        // Constructors.

        ConstructorInfo[] ci = t.GetConstructors(BindingFlags.Public | BindingFlags.Instance);

        Console.WriteLine ("//Constructors");

        PrintMembers (ci);

    }

    public static void PrintMembers(MemberInfo [] ms) {

        foreach (MemberInfo m in ms) {

            Console.WriteLine ("{0}{1}", "     ", m);

        }

        Console.WriteLine();

    }

}

 

 

class Mymemberinfo

{

    public static void Main(string[] args)

    {

        Console.WriteLine ("\nReflection.MemberInfo");

        // Gets the Type and MemberInfo.

        Type MyType =Type.GetType("System.IO.File");

        MemberInfo[] Mymemberinfoarray = MyType.GetMembers();

        // Gets and displays the DeclaringType method.

        Console.WriteLine("\nThere are {0} members in {1}.",

            Mymemberinfoarray.Length, MyType.FullName);

        Console.WriteLine("{0}.", MyType.FullName);

        if (MyType.IsPublic)

        {

            Console.WriteLine("{0} is public.", MyType.FullName);

        }

    }

}

 

 

// This code displays information about the GetValue method of FieldInfo.

class MyMethodInfo {

    public static int Main() {

        Console.WriteLine("Reflection.MethodInfo");

        // Gets and displays the Type.

        Type MyType = Type.GetType("System.Reflection.FieldInfo");

        // Specifies the member for which you want type information.

        MethodInfo Mymethodinfo = MyType.GetMethod("GetValue");

        Console.WriteLine(MyType.FullName + "." + Mymethodinfo.Name);

        // Gets and displays the MemberType property.

        MemberTypes Mymembertypes = Mymethodinfo.MemberType;

        if (MemberTypes.Constructor == Mymembertypes) {

            Console.WriteLine("MemberType is of type All");

        }

        else if (MemberTypes.Custom == Mymembertypes) {

            Console.WriteLine("MemberType is of type Custom");

        }

        else if (MemberTypes.Event == Mymembertypes) {

            Console.WriteLine("MemberType is of type Event");

        }

        else if (MemberTypes.Field == Mymembertypes) {

            Console.WriteLine("MemberType is of type Field");

        }

        else if (MemberTypes.Method == Mymembertypes) {

            Console.WriteLine("MemberType is of type Method");

        }

        else if (MemberTypes.Property == Mymembertypes) {

            Console.WriteLine("MemberType is of type Property");

        }

        else if (MemberTypes.TypeInfo == Mymembertypes) {

            Console.WriteLine("MemberType is of type TypeInfo");

        }

        return 0;

    }

}

 

 

 

// This program lists all the members of the

class ListMembers {

    public static void Main(String[] args) {

        // Specifies the class.

        Type t = typeof (System.IO.BufferedStream);

        Console.WriteLine ("Listing all the members (public and non public) of the {0} type", t);

 

        // Lists static fields first.

        FieldInfo [] fi = t.GetFields (BindingFlags.Static |

         BindingFlags.NonPublic | BindingFlags.Public);

        Console.WriteLine ("// Static Fields");

        PrintMembers (fi);

 

        // Static properties.

        PropertyInfo [] pi = t.GetProperties (BindingFlags.Static |

         BindingFlags.NonPublic | BindingFlags.Public);

        Console.WriteLine ("// Static Properties");

        PrintMembers (pi);

 

        // Static events.

        EventInfo [] ei = t.GetEvents (BindingFlags.Static |

         BindingFlags.NonPublic | BindingFlags.Public);

        Console.WriteLine ("// Static Events");

        PrintMembers (ei);

 

        // Static methods.

        MethodInfo [] mi = t.GetMethods (BindingFlags.Static |

         BindingFlags.NonPublic | BindingFlags.Public);

        Console.WriteLine ("// Static Methods");

        PrintMembers (mi);

 

        // Constructors.

        ConstructorInfo [] ci = t.GetConstructors (BindingFlags.Instance |

         BindingFlags.NonPublic | BindingFlags.Public);

        Console.WriteLine ("// Constructors");

        PrintMembers (ci);

 

        // Instance fields.

        fi = t.GetFields (BindingFlags.Instance | BindingFlags.NonPublic |

         BindingFlags.Public);

        Console.WriteLine ("// Instance Fields");

        PrintMembers (fi);

 

        // Instance properites.

        pi = t.GetProperties (BindingFlags.Instance | BindingFlags.NonPublic |

         BindingFlags.Public);

        Console.WriteLine ("// Instance Properties");

        PrintMembers (pi);

 

        // Instance events.

        ei = t.GetEvents (BindingFlags.Instance | BindingFlags.NonPublic |

         BindingFlags.Public);

        Console.WriteLine ("// Instance Events");

        PrintMembers (ei);

 

        // Instance methods.

        mi = t.GetMethods (BindingFlags.Instance | BindingFlags.NonPublic  

         | BindingFlags.Public);

        Console.WriteLine ("// Instance Methods");

        PrintMembers (mi);

 

        Console.WriteLine ("\r\nPress ENTER to exit.");

        Console.Read();

    }

 

    public static void PrintMembers (MemberInfo [] ms) {

        foreach (MemberInfo m in ms) {

            Console.WriteLine ("{0}{1}", "     ", m);

        }

        Console.WriteLine();

    }

}

 

 

// Code for building SimpleType.dll.

using System;

 

namespace Simple_Type

{

    public class MySimpleClass

    {

        public void MyMethod(string str, int i)

        {

            Console.WriteLine("MyMethod parameters: {0}, {1}", str, i);

        }

 

        public void MyMethod(string str, int i, int j)

        {

            Console.WriteLine("MyMethod parameters: {0}, {1}, {2}",

                str, i, j);

        }

    }

}

 

 

using System;

using System.Reflection;

using System.Globalization;

// The Simple Type namespace.

using Simple_Type;

namespace Custom_Binder

{

    class MyMainClass

    {

        static void Main()

        {

            // Get the type of MySimpleClass.

            Type myType = typeof(MySimpleClass);

 

            // Get an instance of MySimpleClass.

            MySimpleClass myInstance = new MySimpleClass();

            MyCustomBinder myCustomBinder = new MyCustomBinder();

 

            // Get the method information for the particular overload

            // being sought.

            MethodInfo myMethod = myType.GetMethod("MyMethod",

                BindingFlags.Public | BindingFlags.Instance,

                myCustomBinder, new Type[] {typeof(string),

                    typeof(int)}, null);

            Console.WriteLine(myMethod.ToString());

           

            // Invoke the overload.

            myType.InvokeMember("MyMethod", BindingFlags.InvokeMethod,

                myCustomBinder, myInstance,

                    new Object[] {"Testing...", (int)32});

        }

    }

 

    //****************************************************

    //  A simple custom binder that provides no

    //  argument type conversion.

    //****************************************************

    class MyCustomBinder : Binder

    {

        public override MethodBase BindToMethod(

            BindingFlags bindingAttr,

            MethodBase[] match,

            ref object[] args,

            ParameterModifier[] modifiers,

            CultureInfo culture,

            string[] names,

            out object state)

        {

            if(match == null)

                throw new ArgumentNullException("match");

            // Arguments are not being reordered.

            state = null;

            // Find a parameter match and return the first method with

            // parameters that match the request.

            foreach(MethodBase mb in match)

            {

                ParameterInfo[] parameters = mb.GetParameters();

 

                if(ParametersMatch(parameters, args))

                    return mb;

            }

            return null;

        }

 

        public override FieldInfo BindToField(BindingFlags bindingAttr,

            FieldInfo[] match, object value, CultureInfo culture)

        {

            if(match == null)

                throw new ArgumentNullException("match");

            foreach(FieldInfo fi in match)

            {

                if(fi.GetType() == value.GetType())

                    return fi;

            }

            return null;

        }

 

        public override MethodBase SelectMethod(

            BindingFlags bindingAttr,

            MethodBase[] match,

            Type[] types,

            ParameterModifier[] modifiers)

        {

            if(match == null)

                throw new ArgumentNullException("match");

 

            // Find a parameter match and return the first method with

            // parameters that match the request.

            foreach(MethodBase mb in match)

            {

                ParameterInfo[] parameters = mb.GetParameters();

                if(ParametersMatch(parameters, types))

                    return mb;

            }

 

            return null;

        }

 

        public override PropertyInfo SelectProperty(

            BindingFlags bindingAttr,

            PropertyInfo[] match,

            Type returnType,

            Type[] indexes,

            ParameterModifier[] modifiers)

        {

            if(match == null)

                throw new ArgumentNullException("match");

            foreach(PropertyInfo pi in match)

            {

                if(pi.GetType() == returnType &&

                    ParametersMatch(pi.GetIndexParameters(), indexes))

                    return pi;

            }

            return null;

        }

 

        public override object ChangeType(

            object value,

            Type myChangeType,

            CultureInfo culture)

        {

            try

            {

                object newType;

                newType = Convert.ChangeType(value, myChangeType);

                return newType;

            }

            // Throw an InvalidCastException if the conversion cannot

            // be done by the Convert.ChangeType method.

            catch(InvalidCastException)

            {

                return null;

            }

        }

 

        public override void ReorderArgumentArray(ref object[] args,

            object state)

        {

            // No operation is needed here because BindToMethod does not

            // reorder the args array. The most common implementation

            // of this method is shown below.

           

            // ((BinderState)state).args.CopyTo(args, 0);

        }

 

        // Returns true only if the type of each object in a matches

        // the type of each corresponding object in b.

        private bool ParametersMatch(ParameterInfo[] a, object[] b)

        {

            if(a.Length != b.Length)

                return false;

            for(int i = 0; i < a.Length; i++)

            {

                if(a[i].ParameterType != b[i].GetType())

                    return false;

            }

            return true;

        }

 

        // Returns true only if the type of each object in a matches

        // the type of each corresponding entry in b.

        private bool ParametersMatch(ParameterInfo[] a, Type[] b)

        {

            if(a.Length != b.Length)

                return false;

            for(int i = 0; i < a.Length; i++)

            {

                if(a[i].ParameterType != b[i])

                    return false;

            }

            return true;

        }

    }

}

 

 

 

public class CustomBinderDriver

{

    public static void Main (string[] arguments)

    {

    Type t = typeof (CustomBinderDriver);

    CustomBinder binder = new CustomBinder();

    BindingFlags flags = BindingFlags.InvokeMethod|BindingFlags.Instance|

        BindingFlags.Public|BindingFlags.Static;

 

    // Case 1. Neither argument coercion nor member selection is needed.

    args = new Object[] {};

    t.InvokeMember ("PrintBob", flags, binder, null, args);

 

    // Case 2. Only member selection is needed.

    args = new Object[] {42};

    t.InvokeMember ("PrintValue", flags, binder, null, args);

 

    // Case 3. Only argument coercion is needed.

    args = new Object[] {"5.5"};

    t.InvokeMember ("PrintNumber", flags, binder, null, args);

    }

 

    public static void PrintBob ()

    {

        Console.WriteLine ("PrintBob");

    }

 

    public static void PrintValue (long value)

    {

        Console.WriteLine ("PrintValue ({0})", value);

    }

    public static void PrintValue (String value)

    {

        Console.WriteLine ("PrintValue\"{0}\")", value);

    }

  

    public static void PrintNumber (double value)

    {

        Console.WriteLine ("PrintNumber ({0})", value);

    }

}

 

 

Type t = typeof(DefaultMemberAttribute);

DefaultMemberAttribute defMem = (DefaultMemberAttribute)Attribute.GetCustomAttribute(Assembly.GetAssembly(t), t);

MemberInfo[] memInfo = t.GetMember(defMem.MemberName);

 

 

MemberInfo[] memInfo = t.GetDefaultMembers();

 

 

MethodInfo m = t.GetMethod ("MyMethod");

ParameterInfo[] ps = m.GetParameters();

for (int i = 0; i < ps.Length; i++) {

    Console.WriteLine("Default Value == {0}", ps[i].DefaultValue);

}

 

 

 

class MainClass

{

public static void Main()

{

    System.Reflection.MemberInfo info = typeof(MyClass);

    object[] attributes = info.GetCustomAttributes();

    for (int i = 0; i < attributes.Length; i ++)

        {

        System.Console.WriteLine(attributes[i]);

        }

    }

}

. 구현한 예제(첨부파일안의 내용)

 

[Att1("Program Class", 0, IsClass=true)]

    public class _Main

    {

        [Att1("Program TestMethod1 Method", 1, IsClass=false)]

        public void TestMethod1()

        {

            System.Console.WriteLine("in Program.TestMethod1()");

        }

        public static void PrintAnnotation(Type type)

        {

            // 해당ClassAttribute가있는지확인

            Att1[] att1s = (Att1[])Attribute.GetCustomAttributes(type, typeof(Att1));

            if (att1s == null)

            {

                Console.WriteLine(">>Class[{0}], Attributes is null", type);

                return;

            }

            else if (att1s.Length == 0)

            {

                Console.WriteLine(">>Class[{0}], Attributes Length is 0", type);

                return;

            }

 

            for (int i = 0; i < att1s.Length; i++)

            {

                Console.WriteLine("***********\r\nClass[{0}]\r\n\tdesc[{1}], level[{2}], isClass[{3}]",

                    type, att1s[i].Description, att1s[i].Level, att1s[i].IsClass);

            }

 

            // MethodAnnotation있는지확인

            MemberInfo[] memberInfos = type.GetMembers();

            //Console.WriteLine("memberInfos.length[{0}]", memberInfos.Length);

 

            Object objectInstance = type.InvokeMember(null,

                BindingFlags.CreateInstance, null, null, new Object[] {});

//            Console.WriteLine("objectInstance[{0}]", objectInstance);

 

            for (int i = 0; i < memberInfos.Length; i++)

            {

                Console.Write("Method[{0}], Annotaion[", memberInfos[i].ToString());

 

                Att1 att1Method = (Att1)Attribute.GetCustomAttribute(memberInfos[i], typeof(Att1));

                if (att1Method == null)

                    Console.WriteLine("X]");

                else

                {

                    Console.WriteLine("O]\r\n\tdesc[{0}], level[{1}], isClass[{2}]",

                        att1Method.Description, att1Method.Level, att1Method.IsClass);

                   

                    Console.WriteLine("\t[실행전]");

                    type.InvokeMember(

                        memberInfos[i].Name,

                        BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod

                        , null, objectInstance, null);

                    Console.WriteLine("\t[실행후]");

                }

            }

        }

 

        public static void Main(string[] args)

        {

            // 현재클래스나같은프로젝트의다른클래스의Annotation정보출력

            PrintAnnotation(typeof(_Main));

            PrintAnnotation(typeof(Example1));

 

            // 외부Assembly를읽어서Annotation정보출력

//            Assembly assembly = Assembly.LoadFile("D:\\Dev\\_Test\\TestAnnotation\\ExampleLibrary\\bin\\Debug\\ExampleLibrary.dll");

            Assembly assembly = Assembly.LoadFrom("D:\\Dev\\_Test\\TestAnnotation\\ExampleLibrary\\bin\\Debug\\ExampleLibrary.dll");

            Type[] types = assembly.GetTypes();

 

            foreach (Type type in types)

            {

                PrintAnnotation(type);

            }

 

            Console.ReadLine();

}

    }

 

Assembly.LoadFile() A.dll을 호출하면 A.dll에서 참조하는 B.dll은 호출할수 없으나,

Assembly.LoadFrom()으로 호출하면 가능

 

. 참조URL

- Reflection Overview

http://msdn.microsoft.com/en-us/library/f7ykdhsy(VS.71).aspx

- Viewing Type Information

http://msdn.microsoft.com/en-us/library/t0cs7xez(VS.71).aspx

- Dynamically Loading and Using Types

http://msdn.microsoft.com/en-us/library/k3a58006(VS.71).aspx

- Accessing Default Members

http://msdn.microsoft.com/en-us/library/zcfck9kw(VS.71).aspx

- Accessing Default Argument Values

http://msdn.microsoft.com/en-us/library/x0acewhc(VS.71).aspx

- Accessing Custom Attributes

http://msdn.microsoft.com/en-us/library/a4a92379(VS.71).aspx

 

Posted by 파이팅야
,

RTPatch

기타 2009. 2. 13. 20:47

100kb A파일이 있는데 수정되어서 101kb가 되었다면... 배포 시에 101kb를 배포해야 하지만,
RTPatch를 사용하면 변경되어진 byte만 배포되어서 배포시 용량이 90~99%까지 줄일 수 있다고 한다.
50mb가 넘어가면 용량이 커지는 문제도 있다고는 하네...
만약 업데이터를 시스템을 사용하게 되면 해당 파일의 라이센스를 구매하는것도 한방법일듯...

라이센스 있는 회사들...

The first PC Game user of RTPatch was id Software for DOOM. A partial list of users since, with more added every week:

2015, 3D Realms, 3DO, Acony Games, Activision, Apogee, Arcadia, Army Games, Asobo Studios, Atari, Bethesda Softworks, BioWare, Blizzard Entertainment, Bungie Studios, CCP Games, Cliffhanger, Cyberlore, Dragonfly, DreamWorks, Electronic Arts, Ensemble Studios, ePLAYON, Eyedentity, Frogwares, Gamania, Gas Powered Games, Gearbox Software, Gizmo Games, Gravity, Hi-Rez Studios, id Software, Invasions Interactive, Iron Lore Entertainment, KAOS Studios, KingsIsle Entertainment, KTH, Lead Pursuit, Liquid Entertainment, LucasArts, Maxis, Microsoft Game Studios, Midway Home Entertainment, MKO Games, Namco Bandai Games America, NC Soft, NCTrue, Ndoors, Neople, New World Computing, Norseman Games, Nurien, Obsidian Entertainment, Origin, Outspark, Pandemic Studios, PENTAVISION Entertainment, Raven Software, Red Storm Entertainment, Relentless, Rockstar Games, Sega, Sonic Ant, Sierra Entertainment, Sirius Entertainment, Stainless Steel Studios, Stardock, Tencent, Terminal Reality, TimeGate Studios, Ubisoft, WEBZEN, WeMade, Westwood Studios, Wolfpack Studios, Ymir Entertainment, Zenimax

관련 URL :
  http://www.pocketsoft.com/rtpatch_bld.htm
  http://www.gpgstudy.com/forum/viewtopic.php?p=76805&sid=e30a9d2a1359e0dc793f9a123706b0ad

Posted by 파이팅야
,

NUnit 관련

카테고리 없음 2009. 1. 28. 20:25

NUnit은 꾸준히 버전업을 해서 2.5버전에서는 파라미터 있는 메소드도 테스트 가능하게 됨

(http://blog.benhall.me.uk/2008/08/taking-look-at-nunit-25-alpha-3.html)

 

그리고, 요즘에 나온 [PEX]라는 것이 나왔는데요…(마소 2009 1월호에도 기재되어 있음.)

Visual Studio 2008 2010에 들어가게 될꺼라고 합니다. (Visual Studio 2005에서도 실행해도 문제는 없었다고 함)

기능은 간단하게, 소스코드를 분석해 테스트를 위한 [test case(테스트코드)]를 자동으로 생성해 줍니다.

 

NUnit적용하던 관련내용 입니다. 정리하면

- 테스트코드에 category attribute [dev, rc, real]등으로 사용해서 망별로 테스트 해야 하는 테스트 코드들을 분리해서 실행하게 함

- 개발시 테스트 코드 작성하고 Nunit-gui프로그램에 프로젝트 파일을 참조하게 해서 바로 바로 테스트코드 실행결과 보면서 개발

- 개발시 순차적으로 실행되야 하는 테스트코드들은 메소드명을 [_A1, _A2] 와 같이 순차적으로 만들어서 순차적으로 실행되게 함…

- 배포시(.net framework 2.0)에는 아래의 내용이 들어가는 배치파일을 만들어서 배포할 dll생성되기 전에 nunit으로 테스트코드 실행한 후 dll생성되게 함

1.       nunit-console D:\Dev\PCCafeWebSystem\Core\Core.csproj /wait /nologo /include:DEV

2.       aspnet_compiler -v / -p D:\Dev\PCCafeWebSystem\PCCafeWeb D:\Dev\PCCafeWebSystem\PCCafeWeb_Output -f -fixednames -errorstack

3.       aspnet_merge D:\Dev\PCCafeWebSystem\PCCafeWeb_Output -prefix _PCCAFE -errorstack


[아래는 관련 PPT내용]
1.
테스팅의 필요성

      è배포 후 매번 프로세스를 확인하여 이상여부를 확인 합니까?

      è부분배포 시 작업하지 않은 다른 부분에서 오류가 난적이 있습니까?

      è시스템 장애상황을 빠르게 파악하지 못해 대처가 늦었던 적이 있습니까?

      è개발 시 누락 및 중복된 프로세스를 줄이고 싶으십니까?

2. 테스팅의 목표

1.       테스팅은 쉬워야 한다.

2.       테스팅은 빨라야 한다.

3.       테스팅은 자동화 되어야 한다.

4.       테스팅은 철저하게 해야 한다.

5.       테스팅은 개발프로세스에 포함되어야 한다.

3. 테스팅 툴

 

URL

비고

NUnit

http://nunit.org

VSS.NET과 컴파일 시 연동

Free Ware

TestDriven.NET 2.0

http://testdriven.net

VSS.NET 플러그인 지원

Share Ware

NUnitASP

http://nunitasp.sourceforge.net

UI상에서 테스트

통합테스트 가능

속도가 느림

Client Script테스트 불가


4. NUnit
의 소개

4-1. NUnit의 특징

èOpen Source(.NET 버전, JUnit Java버젼)

.NET Framework 1.1 2.0 지원,
           Linux/Solaris/Mac OS X
.NET 개발 Framework
IDE Mono 지원

è Console GUI 지원

4-2. NUnit의 기능

è 단위 테스트(Unit Test)

è 시스템 테스트(System Test)

4-3. Quick Start

namespace bank{

  using System;

  using NUnit.Framework;

 

  [TestFixture]

  public class AccountTest

  {

    Account src;

    Account dest;

 

    [SetUp]      // (반대 [TearDown])

    public void Init()   

    {

      src = new Account();

      src.Deposit(200);

      dest = new Account();

      dest.Deposit(150);

    }

 

    [Test][Description(“이체 테스트”)]

    public void TransferFunds()   

    {

      src.TransferFunds(dest, 100.00f);

      Assert.AreEqual(250, dest.Balance);

      Assert.AreEqual(100, src.Balance);

    }

[Test] [ExpectedException(typeof(InsufficientFund))]

[Category(“Exception”), Category(“Error”)]

    [Property(“TransferFunds”, 300)]

    public void TransferWithInsufficientFunds()

    {

      src.TransferFunds(dest, 300);

    }

 

    [Test]

    [Ignore("Decide how to implement transaction management")]

    [Category(“Error”)]

    public void TransferWithInsufficientFunds()

    {

      try

     {

        src.TransferFunds(dest, 300);

      }

      catch(InsufficientFunds expected)  { }

      Assert.AreEqual(200,src.Balance); Assert.AreEqual(150,dest.Balance);

    }

  }

}

5. NUnit과 테스트 코드

5-1. 테스트 코드

4      작성한 코드가 정상적으로 동작하는지 확인 하기 위한 코드

5-2. 테스트 코드 작성 시 유의사항

4      프로그램에 존재하는 모든 경우의 수를 고려해야 함
   - ID
중복체크 시 [ID중복인 경우]. [ID중복이 아닌 경우] 모두 체크함

4      DB관련 부분 테스트 시
   - DB
Insert/Update Select하여 정확한 데이터가 있는지 확인

4      테스트가 불가능한 경우
   - Stub
을 사용하여 전체적으로 프로세스의 파악에 유리하게 함.
   (
주석 또는 [Ignore] Attribute를 사용하기도 함)

6. NUnit TDD

6-1. TDD 적용

4      코드작성 > 테스트 코드 작성 (X)

4      테스트 코드 작성 > 코드 작성 (O) (예제)

6-2. TDD 장점

4      프로세스의 누락 또는 중복을 판단할 수 있음

4       연관된 다른 프로세스의 이상 여부를 확인할 수 있음

4       테스트코드를 통한 프로세스 파악이 용이함

7. NUnit 적용사례

1.       [Test]에서 그룹화 하는 경우 A05, A10과 같이 명명규칙에 의해 그룹화

2.       실제로 사용되는 망(DEV/RC/REAL) Category를 추가하여 사용

3.       기능상 필요하지만 테스트가 불가능한 경우에는 ignore 또는 주석 사용

4.       Console.out Console.err를 적절히 사용

5.       '배포용 배치파일' NUnit 테스트를 포함 시켜 최종 컴파일 전 한번 더
테스트 가능 (예제)

8. DEMO

1.       VSS.NET NUnit의 연동

2.       NUnit 디버깅

3.       Category Attribute

4.       DB관련 테스트

9. 향후 방향성

1.       매크로와 템플릿을 이용하여 테스트코드 작성 시 편리하게 함

2.       주기적으로 소스세이프의 소스를 NAnt로 컴파일하고 NUnit으로 테스트 하게함

10. 배포용 배치파일

1.       nunit-console D:\Dev\PCCafeWebSystem\Core\Core.csproj /wait /nologo /include:DEV

2.       aspnet_compiler -v / -p D:\Dev\PCCafeWebSystem\PCCafeWeb D:\Dev\PCCafeWebSystem\PCCafeWeb_Output -f -fixednames -errorstack

3.       aspnet_merge D:\Dev\PCCafeWebSystem\PCCafeWeb_Output -prefix _PCCAFE -errorstack

11. VisualStudio의 '빌드 후 이벤트'에 추가해서 자동으로 UnitTest 실행

1.       아래의 그림과 같이 test project의 속성에 들어가서 '빌드 이벤트' 탭을 선택하고 '빌드 후 이벤트 명령줄'의 '빌드 후 편집' 버튼을릭하고 $(SolutionDir)\lib\nunit-console.exe /nologo $(TargetPath)와 같이 설정 한다.


2.
       아래의 그림과 같이 빌드를 하고 '출력(output)'화면을 보면 빌드 후 실행된 Unit Test 결과및 에러내용을 확인할 수 있다. 

 


DB쪽(DAO) 테스트인 경우에는 transaction을 잡고 CRUD를 테스트하고 
transaction을 rollback하면 테스트도 하고 데이터의 변경 반영도 되지 않을 것 같다.

참고
)

- nunit(대중적으로 많이 쓰이고 검증된 오픈소스 프레임웤, 2.5버전에서 파라미터 있는 메소드 테스트도 가능하게 지원)

http://www.nunit.org

- NUnitAsp(asp.net 테스트 툴)

             http://lycobs.springnote.com/pages/921034

- pex(visual Studio 2008~2010에 들어가게 됨, 소스코드작성 후 자동으로 분기문에 들어갈 파라미터들을 찾아서 테스트코드(테스트용 메소드)를 생성해줌)

http://research.microsoft.com/en-us/projects/Pex/

- cs unit (오픈소스 프레임웤, unit과 거의 비슷함)

http://www.csunit.org/download/index.html#latestStable

- parasoft .test

http://www.parasoft.com/jsp/templates/ads/google/googletest1.jsp?redname=googletest1&referred=searchengine%2Fgoogle%2F.test

- dotunit (nunit과 비슷하고 어노테이션 지원하지 않음)

http://dotunit.sourceforge.net/

- WPF Unit test

http://marlongrech.wordpress.com/2007/10/14/wpf-unit-testing/

- Nester

http://nester.sourceforge.net/

- 기타

             - 개발일정을 줄이는 테스팅에 대한 얘기 http://www.ibm.com/developerworks/kr/library/dwclm/20090120/

             - c# testing관련 http://codebetter.com/blogs/darrell.norton/articles/50337.aspx

Posted by 파이팅야
,