태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

달력

11

« 2017/11 »

  •  
  •  
  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  •  
  •  
유닛 테스트를 중요하게 생각하여 설계한 코드라면 HttpContext 같이 ASP.NET 프레임워크에 종속되어 테스트가 불가능해지는 클래스들은 진작에 어댑터 등을 이용하여 분리시켜 두었을 것이다. 하지만 이미 작성된 코드가 많은 상황에서 유닛 테스트를 도입할 때에는 HttpContextBase 클래스가 유용하게 사용될 수 있다.

HttpContextBase 클래스는 ASP.NET MVC에서 쓰이는 클래스라서 (Controller.HttpContext Property 참조) 3.5 SP1부터 쓸 수 있고, System.Web.Abstractions 어셈블리(네임스페이스는 System.Web)를 참조에 추가하면 된다.

HttpContextBase 클래스는 기존의 HttpContext 클래스와 완전히 동일한 멤버들을 노출하고 있고, HttpContext 인스턴스를 쉽게 HttpContextBase 인스턴스로 전환할 수 있도록 HttpContextWrapper 클래스를 같이 제공하고 있다. 포함된 어셈블리도 ASP.NET MVC와는 분리된 어셈블리이다. 따라서 ASP.NET 응용프로그램에서도 기존에 HttpContext 인스턴스를 사용하는 곳에서는 동일하게 HttpContextBase 인스턴스를 사용할 수 있다.

ASP.NET MVC의 목표에 맞게, HttpContextBase의 모든 멤버는 virtual로 선언되어 있어서 HttpContext를 사용하는 코드를 쉽게 유닛 테스트 할 수 있게 된다. (Rhino.Mocks 같은 mock framework을 쓴다면 금상첨화)

비록 HttpContext를 쓰던 곳에 HttpContextBase를 그대로 쓸 수 있다고는 하지만 기존의 ASP.NET 코드 상태에 따라서는 당연히 수정이 필요한 곳이 생긴다.
  • 정적(static)으로 선언된 HttpContex.Current 속성을 직접 사용하는 메서드는 HttpContextBase 인스턴스를 파라미터로 받아서 사용하게 수정해야 한다.
  • 혹은 클래스에 HttpContextBase 형식 필드를 추가해서 그것을 사용하도록 수정해야 한다.
  • new HttpContextWrapper(HttpContext.Current) 같은 형태로 클래스 메서드나 생성자의 파라미터로 넘겨주도록 수정한다.
한 가지 특이하게 수정해야 했던 부분은 Reflection을 사용하는 경우였다. 기존의 코드는 HttpModule 내부에서 HttpContext로부터 HttpWorkerRequest를 얻을 때 Type 클래스를 사용하고 있었다. 

request = (HttpWorkerRequest)type.GetProperty("WorkerRequest", bindingAttr).GetValue(context, null);

다행히 이 경우에는 GetService 메서드를 사용하여 수정할 수 있었고, 이 방법이 정석이라고 생각된다.
request = (HttpWorkerRequest)context.GetService(typeof(HttpWorkerRequest));


이런 식으로 HttpContextBase 클래스를 사용하도록 수정하면, HttpContextBase를 통해서 얻는 Request나 Response 인스턴스에도 동일한 패턴이 적용되어 있으므로 쉽게 테스트 가능한 코드를 얻을 수 있게 된다.
신고
Posted by wafe

댓글을 달아 주세요

  1. 남정현 2009.12.27 02:59 신고  댓글주소  수정/삭제  댓글쓰기

    좋은 아티클 보고 갑니다. 웹 프로젝트 수행 때 좋은 시작점이 될듯합니다. :-)

    • wafe 2009.12.27 13:43 신고  댓글주소  수정/삭제

      들러주셔서 고맙습니다. 운영하고 계신 블로그나 데브피아에좋은 글을 올려주셔서 남정현님 성함이 익숙하게 느껴지는데, 이렇게 제 블로그에 댓글까지 남겨주시니 더 기쁘네요.

      텍스트큐브로 이사하신 줄은 몰랐는데 이제 더 자주 뵐 수 있겠네요 ^^

2009.09.06 11:39

신입사원들과 함께한 TDD 토론 분류없음2009.09.06 11:39

김창준 님강규영 님께서 예전에(켄트 벡의 TDD 책이 번역되어 나오기 전) 만드신 TDD 강좌 동영상을 신입 사원들과 같이 보는 스터디가 회사에서 있었는데, 지난 주에 스터디 정리 미팅이 있어서 참석했다. 요즘 너무 정신없는 터라 글을 한 번 써보자고 하고는 벌써 일주일이 지났네. 나는 스터디에는 참가하지 못하고 정리 미팅에만 참석했지만 참 의미있는 미팅이었다고 생각한다.

신입사원들이지만 참여하는 프로젝트 성격상 유닛테스트와 약간의 TDD 경험이 있는 사람도 있고 아예 유닛 테스트에 대한 경험조차 없는 사람도 있었다. 아예 경험이 없는 사람인 경우에는 역시나 유닛 테스트나 TDD에 대해서 제대로 파악하지 못했음을 알 수 있었다.

유닛 테스트에 대해서도 모르는데 TDD와 동시에 접하게 되면 완전히 혼란스러운 상황에 처하게 되는 것 같다. TDD의 장점으로 쉽게 얘기할 수 있는 리팩토링 시의 안전망 역할은 사실 유닛 테스트의 장점인데 구분을 못한다든가 하는 것이다.

당연한 일이라고 생각한다. 나도 유닛 테스트라는 개념보다 TDD라는 개념을 먼저 접했다. TDD 책을 처음 읽고 나서 도대체 이게 뭘 어쩌라는 건가 했던 감정이 기억난다. 테스트를 작성한다는 건 뭐고 녹색 막대는 또 뭐고... 그래서 책을 다시 읽으면서 책에 나온 예제를 모두 따라해보고, TDD에 관한 글을 마구 구글링했었다.

그런 의미에서 정리 미팅의 질문 리스트에 포함되었 있던 "유닛 테스팅을 잘 하고 있는 상황을 가정한다면, 거기에 TDD를 더 하면 어떤 효과가 있는가?"하는 질문이 진짜 TDD의 장점에 대해서 묻고 있는 질문이라고 생각한다.

TDD는 유닛 테스트를 좀 더 의미있게 할 수 있는 동기를 제공한다는 점에 의미가 있다는 것이 내가 생각할 수 있는 대답이었다. 유닛 테스트를 먼저 생각하고 작성하게 되므로, 나중에 작성할 때보다 테스트 코드 작성에 대한 저항감이 적다. 버그 수정 시에는 특히 유닛 테스트 코드를 작성하는 일을 잊기 쉬운데, 버그 수정 시에도 버그 상황을 재현하는 테스트 코드를 먼저 추가하려는 생각을 갖게 되어 유닛 테스트 커버리지 유지에 도움이 된다.

좀 궁색한 답변이긴 하다. 질문에서 이미 "유닛 테스팅을 잘 하고 있는 상황"을 가정하고 있는데 나는 "TDD 없이 그게 잘 될리가 없고, TDD가 잘 할 수 있게 도와준다"라고 대답한 셈이기 때문이다.

TDD의 장점에 대해서 구글링을 해보면 좀 더 경험적인 장점들에 대해서 많이 얘기하고 있는데, 아직 경험이 짧아 내가 직접 느낀 장점이라고 할 만한건 이정도 뿐인 것 같다.
신고
TAG TDD, Unit Test
Posted by wafe

댓글을 달아 주세요

  1. ntrolls 2009.09.08 06:04 신고  댓글주소  수정/삭제  댓글쓰기

    별 상관없는 이야기이긴 한데;;;

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

    .Net 유닛테스팅 자동생성 툴. 우리 랩 친구도 잠깐 참여했던 프로젝트이니 잘 되나 한 번 구경해보시라 :)

    • wafe 2009.09.10 01:39 신고  댓글주소  수정/삭제

      마소 잡지에서 보고 관련이 있으실 거 같다는 생각이 들었는데 역시나 였군요 :) 이런게 가능하다니 마치 다른 세상의 얘기인 거 같다는 생각이 ㅎㅎ

    • ntrolls 2009.09.21 18:59 신고  댓글주소  수정/삭제

      뭘... 속을 들여다보고 나면 다 그냥 그런 거라오 흐흐.

  2. Mini 2009.09.08 14:47 신고  댓글주소  수정/삭제  댓글쓰기

    TDD 가 unittest 의 형태로 드러나긴 하지만, 생각과 design 을 도와주는 도구로서도 작동하는 것 같습니다. 창준님께서는 TDD 를 시작하기전에 essense 가 뭘까를 생각하고 시작을 하면 NOO 적인(살아있는, 세포가 분영하는 듯한) TDD 를 할 수 있다고 하더군요. 저도 요즘 그런 훈련을 많이 하고 있구요.

    • wafe 2009.09.10 01:43 신고  댓글주소  수정/삭제

      에센스라고 하시니 클래스 설계 시의 응집성 결합성 같은 개념이 떠오르네요. 클래스의 책임을 명확히 하지 않으면 클래스도 커지고 덩달아 테스트 코드는 기하 급수적으로 커진다는 측면에서 나쁜 냄새를 빨리 맡을 수 있는 효과도 기대할 수 있다는 생각이 문득 듭니다.

      NOO에 대해서 많이 접하지를 못해서 에센스를 이런 식으로 연결시켜도 될지 모르겠네요 :)

2009.05.23 03:36

Google Test의 데이터 기반 테스트 분류없음2009.05.23 03:36

Google Test에서도 MBUnit의 RowTestNUnit의 TestCase 같은 데이터 기반 테스트라는 개념을 지원한다. Google Test에서는 이 개념을 Value-Parameterized Tests라고 부른다. 코드는 동일한데 사용하는 데이터 값 몇 개만 바뀌는 테스트 케이스가 있을 때, 코드 중복을 없애주면서도 어떤 테스트 케이스가 실패하고 성공하는지 정확하게 알려주는 유용한 기능이다.

 

그런데 아무래도 C# 보다는 유연성이 떨어지는(?) C++이라 쓰기가 마냥 쉽지만은 않아서 좀 정리를 해 둘 필요가 있다. 템플릿을 써서 구현한 기능이라 컴파일 에러라도 한 번 나면 좀 골치가 아프긴 하지만, Visual C++ 2008의 템플릿 관련 에러 메시지는 엄청나게 친절하기 때문에 미리 걱정할 필요는 없을 듯.

  1. #include "gtest/gtest.h"

    #include "gmock/gmock.h"

    #include <tuple>

     

    using testing::Return;

     

    namespace

    {

    // ParamType 구성

    // TestWithParam<T>가 받는 테스트 데이터는 T 타입의 값 하나이기 때문에, 데이터 여러 개를 넘기려고 tuple을 사용한다.

    typedef std::tr1::tuple<bool, MsoTriState, MsoAnimateByLevel, MsoTriState, MsoTriState, MsoAnimateByLevel> ParamType;

     

    // Value-Parameterized Tests를 위해서는 비어있는 Fixture라도 하나 만들어야한다.

    // TestWithParam<T>를 상속받는 것 외에는 일반적인 Test Fixture와 동일하다.

    class TestEffectDataSetEffectInformationFixture

        : public testing::TestWithParam<ParamType>

    {

    };

     

    // Value-Parameterized Tests를 위한 테스트 메서드

    // 여기서는 TEST_P 매크로를 쓴다. 일반적인 Fixture를 쓸 때에는 TEST_F 매크로를 쓰는 것과 다르다.

    TEST_P(TestEffectDataSetEffectInformationFixture, TestSetEffectInformation)

    {

        bool recheckRun;

        MsoTriState recheckRetValue;

        MsoAnimateByLevel levelEffectRetValue;

        MsoTriState animBgRetValue;

        MsoTriState animBgExpected;

        MsoAnimateByLevel levelEffectExpected;

     

        // GetParam() 함수를 써서 테스트 데이터를 얻는다.

        // 여기서는 데이터가 tuple 이라서 tie()를 써서 값을 얻는다.

        std::tr1::tie(recheckRun, recheckRetValue, levelEffectRetValue, animBgRetValue, animBgExpected, levelEffectExpected) = GetParam();

     

        MockEffectAdaptor ea;

        MockEffectInformationAdaptor eia;

     

        if (recheckRun) {

            EXPECT_CALL(ea, GetAnimateBackgroundRechecked())

                .WillOnce(Return(recheckRetValue));

        }

        else {

            EXPECT_CALL(ea, GetAnimateBackgroundRechecked())

                .Times(0);

        }

     

        EXPECT_CALL(eia, GetBuildByLevelEffect())

            .WillOnce(Return(levelEffectRetValue));

        EXPECT_CALL(eia, GetAnimateBackground())

            .WillOnce(Return(animBgRetValue));

     

        EffectData ed;

        ed.SetEffectInformation(ea, eia);

     

        ASSERT_EQ(animBgExpected, ed.AnimateBackground);

        ASSERT_EQ(levelEffectExpected, ed.BuildByLevelEffect);

    }

     

    // Value-Parameterized Tests에 테스트 데이터를 제공

    INSTANTIATE_TEST_CASE_P(Prefix, TestEffectDataSetEffectInformationFixture,

        testing::Values(

            ParamType(true, msoTrue, msoAnimateLevelNone, msoFalse, msoTrue, msoAnimateLevelNone),

            ParamType(true, msoFalse, msoAnimateLevelNone, msoFalse, msoFalse, msoAnimateLevelNone),

            ParamType(false, msoFalse, msoAnimateTextByAllLevels, msoFalse, msoFalse, msoAnimateTextByAllLevels),

            ParamType(false, msoFalse, msoAnimateLevelNone, msoTrue, msoTrue, msoAnimateLevelNone)

        ));

    } // anonymous namespace

 

테스트 실행 결과는 이런 식으로 나온다.

3>[ RUN      ] Prefix/TestEffectDataSetEffectInformationFixture.TestSetEffectInformation/0
3>[       OK ] Prefix/TestEffectDataSetEffectInformationFixture.TestSetEffectInformation/0
3>[ RUN      ] Prefix/TestEffectDataSetEffectInformationFixture.TestSetEffectInformation/1
3>[       OK ] Prefix/TestEffectDataSetEffectInformationFixture.TestSetEffectInformation/1
3>[ RUN      ] Prefix/TestEffectDataSetEffectInformationFixture.TestSetEffectInformation/2
3>[       OK ] Prefix/TestEffectDataSetEffectInformationFixture.TestSetEffectInformation/2
3>[ RUN      ] Prefix/TestEffectDataSetEffectInformationFixture.TestSetEffectInformation/3
3>[       OK ] Prefix/TestEffectDataSetEffectInformationFixture.TestSetEffectInformation/3

 

이 예제 코드에서는 테스트 데이터를 만들 때 그냥 Values()만 썼는데, Combine() 같은 걸 쓰면 주어진 값의 모든 조합을 생성해서 테스트해 준다거나 하는 기능은 그냥 코드 중복을 막는다는 차원을 넘어서는 멋진 기능이라고 생각된다.

 

그 외에 다른 사용법은 공식 문서를 보면 되는데, 실제 사용하면서 생기는 궁금증을 해결하기 위해서는 소스 코드에 주석 형태로 들어있는 사용 예제들을 보는게 좋다.

이 글은 스프링노트에서 작성되었습니다.

신고
Posted by wafe

댓글을 달아 주세요

2009.04.28 11:17

Google Test의 문자열 비교 Assertion 분류없음2009.04.28 11:17

UnitTest++과 비교했을 때 상대적으로 Google Test가 좋은 점 중에 한 가지는 문자열 비교이다. Google Test는 wide character 문자열도 잘 비교해주기 때문에 다음과 같은 문자열 비교 assertion을 써서 실제 값과 다른 경우에는 아래와 같이 문자열 값을 실패 메시지에 포함시켜서 보여준다.

  1. ASSERT_STREQ(_T("-111"), xe->GetProperty(_T("Canvas.Left")));

(노파심에 프로젝트명은 지움)

GoogleTestStringComp.png

 

Google Test의 문자열 비교 assertion에는 이런 것들이 있다.

Fatal assertion Nonfatal assertion
ASSERT_STREQ(expected_str, actual_str); EXPECT_STREQ(expected_str, actual_str);
ASSERT_STRNE(str1, str2); EXPECT_STRNE(str1, str2);
ASSERT_STRCASEEQ(expected_str, actual_str); EXPECT_STRCASEEQ(expected_str, actual_str);
ASSERT_STRCASENE(str1, str2); EXPECT_STRCASENE(str1, str2);

이 글은 스프링노트에서 작성되었습니다.

신고
Posted by wafe

댓글을 달아 주세요

2009.04.23 23:00

shared_ptr의 custom deleter 사용법 분류없음2009.04.23 23:00

내가 처음 custom deleter를 봤을 때에는, shared_ptr 생성자에서 한 번 custom deleter를 지정해주면 그 다음부터 reset()을 하더라도 항상 처음에 지정했던 deleter를 불러줄 거라는 기대가 있었다. 그래서 테스트를 해봤더니 그런게 아니네. custom deleter를 유지하고 싶다면 reset()을 할 때 deleter도 같이 넘겨줘야 한다.

 

아래 테스트 코드는 custom deleter를 지정하지 않고 reset()한 경우에는 custom deleter가 호출되지 않는다는 걸 Google Test를 이용해서 보여주는 코드이다.

 

  1. class TestSharedPtrFixture : public testing::Test
    {
    public:
       std::stringstream ss;

       TestSharedPtrFixture()
           : ss(std::stringstream::out | std::stringstream::out)
       {
       }

       void Deleter(int* p)
       {
           ss << "dtor()" << std::endl;
           delete p;
       }
    };

    // shared_ptr 기능을 제대로 알기 위한 테스트
    // shared_ptr reset() 메서드에서 dtor를 별도로 지정하는 경우 reset() 메서드를 실행할 때마다 dtor를 지정해줘야 함
    TEST_F(TestSharedPtrFixture, TestReset)
    {
       ss.str("");

       std::tr1::shared_ptr<int> sp;
       ASSERT_EQ(NULL, sp.get());

       sp.reset(new int(9), std::bind1st(std::mem_fun1(&TestSharedPtrFixture::Deleter), this));
       sp.reset(new int(8));
       sp.reset();

       ASSERT_EQ("dtor()\n", ss.str());
    }

    // shared_ptr 생성자에서 dtor를 별도로 지정하는 경우 reset() 메서드를 실행할 때마다 dtor를 지정해줘야 함
    TEST_F(TestSharedPtrFixture, TestCtor)
    {
       ss.str("");

       std::tr1::shared_ptr<int> sp(new int(9), std::bind1st(std::mem_fun1(&TestSharedPtrFixture::Deleter), this));
       ASSERT_EQ(9, *sp.get());

       sp.reset(new int(8));
       sp.reset();

       ASSERT_EQ("dtor()\n", ss.str());
    }

 

이 글은 스프링노트에서 작성되었습니다.

신고
Posted by wafe

댓글을 달아 주세요

2009.04.18 03:15

Google Test & Visual Studio 2008 분류없음2009.04.18 03:15

  1. google test를 다운받는다.(gtest-1.3.0)
  2. 필요한 폴더만 남기고 나머지는 다 지운다. 실제 프로젝트에서 쓸 때에는 include, msvc, src 폴더 외에는 필요없다.
  3. msvc 폴더의 파일 중에도, 프로젝트에서 쓸 때에는 gtest.vcproj 파일 외에는 다 필요 없으므로 지워버린다.
  4. VS2008로 gtest.vcproj 파일을 열어서 2008 포맷으로 변환해준 후 VS를 닫는다. (닫을 때 sln을 저장할 것인지 물어보는데 저장하지 않음을 선택한다.)
  5. 프로젝트를 만든다.
  6. 솔루션 폴더에 gtest-1.3.0 폴더를 통채로 옮긴다.
    1. 여러 사람이 같이 작업하는 프로젝트에서 구글 테스트 프레임워크를 쓰기에는, 솔루션 폴더에 통채로 포함시키는 편이 공유하기에 편하다.
    2. 현재 사용중인 버전을 아는 것이 좋으니까 gtest-1.3.0 같은 식으로 폴더 이름에 프레임워크 버전을 포함시켜 두도록 한다.
  7. 솔루션에 "기존 프로젝트 추가"를 해서 gtest.vcproj 를 추가한다.
  8. 솔루션에 테스트 프로젝트를 추가한다.
    1. VC++ > 일반 > 빈 프로젝트를 추가하도록 한다.
  9. 테스트 프로젝트의 참조에 gtest 프로젝트를 추가한다.
  10. gtest-1.3.0/src 폴더에 있는 gtest_main.cc 를 테스트 프로젝트 폴더로 복사하고, 테스트 프로젝트에 추가한다.
  11. 테스트 프로젝트의 "추가 포함 디렉터리"에 $(SolutionDir)\gtest-1.3.0\include 를 추가한다.
  12. 테스트 프로젝트와 gtest 프로젝의 구성 속성에서 "C/C++ > 코드 생성" 페이지의 "런타임 라이브러리"를 맞춰준다. (여기서는 다중 스레드 디버그(/MTd)로 맞췄다.)
  13. 테스트 프로젝트의 구성 속성에서 "빌드 이벤트 > 빌드 후 이벤트" 페이지의 "명령줄"에 $(TargetPath) 를 설정해준다. 이렇게 하면 프로젝트가 빌드 된 후 바로 테스트 프로젝트가 실행되고, 실행 결과가 VS 출력 창에 나타난다. gtest-output.png
  14. 실패하는 테스트 케이스가 있는 경우에는 컴파일 에러와 마찬가지로 출력 창에 소스 파일과 라인이 표시되기 때문에 마우스로 더블클릭하면 실패한 라인으로 바로 이동된다.

 

참조:

 

이 글은 스프링노트에서 작성되었습니다.

신고
Posted by wafe

댓글을 달아 주세요

  1. U.Seung 2009.04.19 17:58 신고  댓글주소  수정/삭제  댓글쓰기

    저도 요즘
    Google Test 써보고 있는데ㅋ

    C++ Unit Testing도구는 쓸때마다 n%씩 부족한 느낌이 들어서 이거.ㅎㅎ

    • wafe 2009.04.19 23:37 신고  댓글주소  수정/삭제

      언어가 C++이니 뭐 ㅎㅎ
      그래도 현재로서는 Google Test + Google Mock 조합이 최강이 아닐까 싶네. 아직 Google Mock은 문서만 보는 중이긴 하다만 ;;

  2. decoder 2009.04.20 08:48 신고  댓글주소  수정/삭제  댓글쓰기

    헐퀴 ;; 트랙백 보고 날라왔습니다~~
    윈도 프로그램 만들때 도움되겠네요. 감사합니다 :)

    • wafe 2009.04.20 14:08 신고  댓글주소  수정/삭제

      구글 테스트에 대해 검색하다가 decoder님 블로그에서 정보를 얻었거든요. 저도 뭔가 도움될까 싶어서 트랙백 날려봤습니다. ^^;

  3. 오늘도 공부... 2009.06.26 20:27 신고  댓글주소  수정/삭제  댓글쓰기

    좋은 글 감사드립니다. 적힌 글을 따라서 진행을 하는데, 제대로 되지 않아서 글을 남깁니다.
    실제 테스트에 들어있는 CMoney(개발 프로젝트)에 대한 CMoneyTest 파일은 테스트 프로젝트의 포함을 하는가요? 아니면 개발 프로젝트에 포함을 하는가요? 저는 테스트 프로젝트에 포함을 시켰는데, 에러가 발생을 하네요. T.T 그렇다고 CMoneyTest를 개발 프로젝트에 포함을 시켜면 gtest에 대한 "포함 파일, 라이브러리"등을 포함시켜야 되는데, 그것은 좀 아니듯해서... 질문만 남겨서 죄송합니다.

    • wafe 2009.06.29 17:51 신고  댓글주소  수정/삭제

      안녕하세요 찾아주셔서 고맙습니다.

      테스트 코드가 들어가는 소스 파일들(CMoneyTest 등)은 테스트 프로젝트에 넣어야 됩니다.

      gtest에 같이 제공되는 샘플에 CMoneyTest 라는게 있나해서 찾아봤더니 그런 게 있지는 않군요. 어떤 에러인지 몰라 도움을 못 드리는게 안타깝네요.

      참고로 제가 겪었던 에러 중에 제일 흔한 것은 테스트 프로젝트와 제품 프로젝트의 '런타임 라이브러리'를 동일하게 맞추지 않은 경우였습니다.

  4. zippolook 2010.06.03 12:13 신고  댓글주소  수정/삭제  댓글쓰기

    설명 감사합니다. 저는 1.5버전으로 만들어 봤어요.
    wafe님의 글을 바탕으로 그림 추가하여 제 블로그에 포스팅 하려고 합니다. 그래도 되겠죠?

  5. mooni 2010.06.15 21:23 신고  댓글주소  수정/삭제  댓글쓰기

    안녕하세요. 좋은 글 우선 감사드려요 ^^
    저도 윗분들과 똑같이 하는데 계속 LNK2019 에러가 나서요. 하루 종일 삽질을 하고 있네요.
    제가 님이 쓰신 글을 잘못이해하고 있는건 아닌지 확인 좀 해수시면 감사하겠습니다.
    gtest-1.5를 받아 세팅했구요, 솔루션 안에 A 프로젝트, ATest 프로젝트, gtest 이렇게 세개의 프로젝트가 있습니다. gtest는 글 처럼 기존 프로젝트를 추가했구요. A 프로젝트에 gtest에 있는 sample1 파일들을 넣고, ATest 프로젝트에 gtest_main.cc 와 sample1_unittest.cc 를 넣고 빌드를 하게 되면 계속 LNK2019 에러가 나네요. 글에 적힌 부분은 모두 따라했구요.
    혹시 왜 에러가 나는지 아시면 도움 좀 부탁드리겠습니다. 아,
    그리고 테스트 프로젝트의 구성 형식은 응용 프로그램(.exe)로 해놓는게 맞나요? sample1 을 모두 비우고 코드가 없이 실행할 경우 콘솔 창에 제대로 출력이 되는데 sample1 코드를 작성하면 문제가 나네요.
    음.. 장문의 글이 되었네요. ㅎ 염치없지만 혹시 아시면 도움 좀 부탁드리겠습니다.

    • wafe 2010.06.20 20:22 신고  댓글주소  수정/삭제

      블로그를 자주 확인하지 않다보니 답장이 늦었네요.

      1. 프로젝트는 EXE로 해 놓으시면 됩니다.

      2. 제가 지금 당장은 직접 돌려볼 수가 없어서 제 추측으로만 쓰게 되는 걸 좀 양해해주시면 좋겠습니다.

      링크 에러가 발생하는 건 A 프로젝트에 있는 소스 파일을 ATest 프로젝트에 추가해주지 않았기 때문이라고 생각됩니다. ATest 프로젝트에 오른쪽 클릭해서 기존파일 추가 기능을 써서 테스트 대상이 되는 cpp 파일을 추가해주면 될거라고 생각됩니다.

      그래도 링크 에러가 계속된다면 sample1을 컴파일하는데 필요한 lib 같은 게 ATest 프로젝트에는 추가되지 않았다든지 하는 문제일 것 같습니다.

  6. 손님 2010.06.22 22:34 신고  댓글주소  수정/삭제  댓글쓰기

    저도 mooni 님과 똑같은 증상이 나타나네요..
    하루종일 봐도 LNK2019 문제가 해결이 안되는데.. 혹시 원인이 뭘까요?
    1.3 버전으로 해도 증상이 같네요.. ㅜㅜ

    • 손님 2010.06.23 09:05 신고  댓글주소  수정/삭제

      해결했습니다.. ㅠㅠ
      mooni 님도 저랑 똑같이 해결하시면 될 듯 한데요..
      프로젝트가 아닌 솔루션 속성창에 가시면 project dependencies 라는 메뉴가 있습니다.
      거기서 테스트프로젝트가 구글 테스트를 depend on 하도록 설정 해주니까 링크 에러가 없어 졌네요...

2009.04.09 10:42

Silverlight Code Coverage 분류없음2009.04.09 10:42

Silverlight용 Unit Testing Framework는 Jeff Wilcox의 Microsoft Silverlight Unit Test Framework이 제일 유명하다.

Visual Studio Team System Developer Edition 에서는 "코드 검사"라는 기능을 통해서 유닛 테스트 실행 후 커버리지를 보여주는 기능을 포함하고 있다. 그런데 이것은 닷넷 어플리케이션에만 적용되고, Silverlight 어플리케이션에서는 쓸 수 없다.

Silverlight는 보안을 위해서 별도의 분리된 환경에서 실행되므로, NCover등이 사용하는 기존의 방식으로는 커버리지를 측정할 수 없다고 한다. (어떤 방식인지 찾아보면 재미있을 듯) 즉, Silverlight 어플리케이션의 유닛 테스트에서 코드 커버리지를 측정하기 위해서는 유닛 테스팅 툴과 연계된 커버리지 툴을 쓰는 것이 가장 좋을 것이다.

MS Silverlight Unit Test Fx 문서를 보면 CodeCoverage라는 클래스가 정의되어 있어서 소스까지 들여다봤는데 결국 얻은 것은 아직 구현되지 않은 미래를 위한 기능이라는 것이었다.

아예 SilverUnit 이라는 다른 테스트 프레임워크를 쓰면 커버리지를 보는 것이 가능할 것 같기는 하다. Typemock Isolator 라는 걸 쓰면 특정 프레임워크(WPF나 Silverlight, SharePoint 등)에 종속적인 부분을 런타임에 대체해버려서 의존성을 제거할 수 있는 것 같다. 그렇게 의존성을 제거하면 일반 닷넷 환경에서 테스트를 돌릴 수 있는 듯. 그걸 기반으로 해서 Silverlight를 테스트하라고 만들어놓은 프레임워크 인 거 같은데, 무료로 제공되긴 하지만 정작 Isolator는 가격이 상당해서 포기해버렸다.

결론은 MS Silverlight Unit Test Framework에서 커버리지 기능이 구현될 때까지는 그냥 기다리자는 것.

신고
Posted by wafe

댓글을 달아 주세요



티스토리 툴바