2009년 11월 12일 목요일

최근 열심히 즐기고 있는 게임


최근 열심히 즐기고 있는 게임. 흔히 FPS 디아블로라고 부르는 게임임. 헉슬리가 FPS+RPG가 잘못 혼합된 형태라면 이 게임은 잘된 케이스임. 발매될 때까지도 모르고 있었던 게임인데, 정말 물건임!!!
지금 회사에서 Unreal을 사용해서 NPR느낌으로 게임을 만들고 있어서 Unreal을 사용해서 첨으로 NPR느낌의 게임을 만드는지 알았는데, 이 녀석이 나오면서 이제 그냥 따라쟁이 게임이 되겠군.

GoogleTestPrimer(번역 진행중)

소개: 왜 구글 C++ 테스트 프레임워크인가?

구글 C++ 테스팅 프레임워크는 여러분이 더 나은 C++ 테스트들을 작성할 수 있도록 도와줍니다.

어떤 요소들이 좋은 테스트를 만드는지 그리고 어떻게 구글 C++ 테스팅 프레임워크가 적절한지 그 이유는 다음과 같습니다:
  1. 테스트들은 독립적이고 반복적이어야 합니다. 다른 테스트들의 결과로서 성공이나 실패한 임의의 테스트를 디버깅하는 것은 고통스럽습니다. 구글 C++ 테스팅 프레임워크는 서로 다른 객체에 대해서 그것들 각각마다 작동하기때문에 테스트들이 서로 독립적입니다. 임의의 테스트가 실패했을 때, 구글 C++ 테스팅 프레임워크는 여러분이 신속히 디버깅을 하기 위해서 그 테스트만 독립적으로 실행할 수 있도록 해줍니다.
  2. 테스트들은 잘 구성되어야하고 테스트되는 코드의 구조를 반영해야합니다. 구글 C++ 테스팅 프레임워크는 자료와 서브루틴들을 공유하는 연관된 테스트들을 테스트 케이스들로 그룹화합니다. 이러한 공통 패턴은 인지하기 쉽고 테스트들을 유지하기 쉽도록 해줍니다. 이러한 일관성은 사람들이 프로젝트들을 전환하고 새로운 코드 베이스위에서 다시 작업을 시작할 때 특히 유용합니다.
  3. 테스트들은 이식성이 좋고 재사용 가능해야 합니다. 오픈-소스 커뮤니티들은 플랫폼 중립적인 많은 코드들을 가지고 있고 그것들의 테스트들도 또한 플랫폼 중립적이어야 합니다. 구글 C++ 테스팅 프레임워크는 서로 다른 OS들, 서로 다른 컴파일러들(gcc, MSVC, 기타등등)에서 작동합니다. 그래서 구글 C++ 테스팅 프레임워크 테스트들은 여러 설정들에서 손쉽게 작동합니다.(알림 현재 릴리즈는 Linux에서만 빌드 스크립트들을 포함하고 있습니나. 현재 다른 플랫폼에 대한 스크립트들을 작업 중 입니다.)
  4. 테스트들이 실패했을 때, 테스트들은 문제에 대한 정보를 가능한 많이 제공해야합니다. 구글 C++ 테스팅 프레임워크는 첫 번째 테스트 실패에서 멈추지 않습니다. 대신, 현재 테스트만 중단하고 다음 테스트를 진행합니다. 또한 여러분이 치명적이지 않은 실패들을 보고하도록 테스트들을 설정할 수 있고 그러한 테스트들 이후에 현재 테스트가 진행됩니다. 따라서 여러분은 한번의 실행-수정-컴파일 사이클안에 여러 버그들을 발견하고 수정할 수 있습니다.
  5. 테스팅 프레임워크는 테스트 작성자들이 허드렛 일에서 해방시켜주고 그 테스트 내용에만 집중할 수 있도록 해줍니다. 구글 C++ 테스팅 프레임워크는 자동적으로 정의된 모든 테스트들을 기록해서 여러분이 테스트들을 실행하기 위해서 그것들을 애뮬레이션하는 것을 요구하지 않습니다.
  6. 테스트들은 신속해야합니다. 구글 C++ 테스팅 프레임워크를 사용함으로써, 여러분은 테스트들사이에 공유된 자원들을 재사용할 수 있으므로 각각에 의존적인 테스트들을 만들 필요없이 단 한번만 set-up/tear-down을 호출하면 됩니다.
구글 C++ 테스팅 프레임워크가 가장 대중적인 xUnit 아키텍쳐에 근거하고 있기때문에, 만약 이전에 JUnit이나 PyUnit을 사용해본 경험이 있다면, 익숙하다고 느낄 겁니다. 만약 그런 경험이 없다고 해도, 한 10분 정도 기초를 익히면 바로 시작할 수 있습니다.

알림 : 이하 Google C++ 테스팅 프레임워크를 구글 테스트라고 합니다.

새로운 테스트 프로젝트 설정하기

구글 테스트를 사용해서 테스트 프로그램을 작성하기 위해서, 여러분은 구글 테스트를 라이브러리로 컴파일하고 여러분의 테스트에 그것을 링크해야합니다. 우리는 몇몇 대표적인 빌드 시스템들(Visual Studio의 msvc, 맥 Xcode의 xcode, GNU make의 make, 볼랜드 C++ 빌더의 codegear, Scons의 scons그리고 구글 테스트 루트 디렉토리안에 자동화 스크립트 툴들)에 대한 빌드 파일들을 제공합니다. 만약 여러분의 빌드 시스템이 이러한 것들 중 하나가 아니라면, 여러분은 어떻게 구글 테스트가 컴파일되어야 하는지에 대해서 배우기 위해서 make/Makefile을 살펴볼 수 있습니다(기본적으로 여러분은 헤더 검색 경로로 GTEST_ROOT/include로 설정하고 src/gtest-all.cc를 컴파일하고 싶을 것입니다. 여기서 GTEST_ROOT는 구글 테스트의 루트 디렉토리입니다).

여러분이 구글 테스트 라이브러리를 컴파일한다면, 여러분의 테스트 프로그램에 대한 프로젝트를 생성하거나 타겟을 빌드할 수 있습니다. 테스트를 컴파일할 때, 컴파일러가 를 찾을 수 있도록 헤더 검색 경로안에 GTEST_ROOT/include를 설정해야합니다. 구글 테스트 라이브러리를 링크하기 위해서 테스트 프로젝트를 설정합니다(예를 들면, Visual Studio에서, 이것은 gtest.vcproj에 대한 의존성을 추가하면 됩니다).

만약 여러분이 질문이 있다면, 어떻게 구글 테스트의 자체 테스트들이 빌드되는지 살펴보시고 그것들을 예제들로 사용하세요.

기본 개념들

구글 테스트를 사용할 때, 임의의 조건이 참인지 아닌지를 판별하는 구문들인 단정문들 작성함으로써, 시작합니다. 임의의 단정문의 결과는 성공, 치명적이지 않은 실패 또는 치명적인 실패일 수 있습니다. 만약 치명적인 실패가 발생한다면, 그것은 현재 함수를 중단합니다. 반대로 그렇지 않다면, 프로그램은 일반적으로 계속 진행됩니다.

테스트들이 테스트되는 코드의 행위를 검증하기 위해서 단정문들을 사용합니다. 만약 임의의 테스트가 충돌하거나 실패한 단정문을 가진다면, 그때 테스트는 실패한 것이고 그렇지 않다면, 성공한 것입니다.

테스트 케이스는 하나 이상의 테스트들을 포함합니다. 여러분은 테스트들을 테스트되는 코드의 구조를 반영하는 테스트 케이스들로 그룹화해야 합니다. 하나의 테스트 케이스안에 다수의 테스트들이 공통의 객체들과 서브루틴들을 공유해야할 필요가 있을 때, 여러분은 그것들을 하나의 테스트 픽스쳐 클래스에 담을 수 있습니다.

테스트 프로그래은 다수의 테스트 케이스들을 포함할 수 있습니다.

우리는 이제 개별적인 단정문 수준에서 시작해서 테스트들과 테스트 케이스들 점진적으로 구성하면서 하나의 테스트 프로그램을 어떻게 작성할 수 있는지 설명할 것 입니다.

단정문들

구글 테스트 단정문들은 함수 호출들과 유사한 매크로들입니다. 여러분은 클래스 또는 함수의 행위에 대한 단정문들을 작성함으로써 그것들을 테스트합니다. 하나의 단정문이 실패했을 때, 구글 테스트는 실패 메세지와 함께 그 단정문의 소스 파일과 행 번호를 출력합니다. 여러분은 또한 구글 테스트의 메세지에 추가적으로 독자적인 실패 메세지를 제공할 수 있습니다.

단정문들은 동일한 테스트를 수행하는 쌍들로 나오기도 하지만, 그 함수에 대해 서로 다른 효과를 가집니다. ASSERT_* 버전들은 실패했을 때, 치명적인 실패를 생성하고 그 함수를 중단합니다. EXPECT_* 버전들은 치명적이지 않은 실패를 생성하지만, 그 함수를 중단하지는 않습니다. 보통 EXPECT_*를 더 선호하기 때문에, 한번 테스트에 하나 이상의 실패들이 보고될 수 있습니다. 하지만, 단정문이 실패했을 때, 더 이상 진행할 필요가 없을 경우라면, 여러분은 ASSERT_*를 사용합니다.

실패된 ASSERT_*는 즉시적으로 현재 함수로 부터 반환되기 때문에, 그 이후로 나오는 정리 코드들은 생략될 수도 있습니다. 이러한 이유로 공간 누수가 발생할 수도 있습니다. 그 누수의 현상에 따라서, 수정할 가치가 있을 수도 없을 수도 있습니다 - 그래서 단정 오류에 추가적으로 힙 오류를 체크할 것인가를 고려해야합니다.

독자적인 실패 메세지를 제공하려면, 단순히 그 메세지를 << 연산자나 연속적인 << 연산자를 사용해서 그 매크로에 메세지를 스트리밍합니다. 예를 들면,

ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";

for (int i = 0; i < x.size(); ++i) {
    EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
}
C 문자열과 string 객체와 같이 ostream으로 스트림될 수 있는 어떤 것이라도 단정 매크로로 스트림될 수 있습니다. 만약 와이드 string(윈도우즈 유니코드 모드에서 wchar_t*, TCHAR*나 std::wstring)이 단정문으로 스트림된다면, 그것은 출력될 때 UTF-8으로 변환될 것 입니다.

기본적인 단정문들

2009년 11월 11일 수요일

동생이야기


작년에 Daum에서 웹툰 작가로 데뷔해서 이런저런 집안 사정으로 연재 내내에 악플로 시달려오다가 한 동안 다음 작품을 준비하는 기간이 길어졌지만, 올해 다시 시작한 연재물이 바로 Hang-Off 형인 나도 황당하게도 바이크 만화였던 것이다. 물론 동생이 바이크를 좋아해서 고등학교때도 바이크로 타고 다니긴 했지만, 어떻게 이야기를 진행할지 궁금했는데 24화나 진행 중......

이제 나보다 훨씬 잘될 것 같지만, 그래도 형이라서 그런지 항상 걱정이다.


헝가리언 표기법의 무용론.

실용주의 프로그래머를 읽다보니, 저자가 헝가리언 표기법은 객체지향 시스템에서 전혀 적절하지 못하다는 이야기가 나오는데, 전적으로 동의한다.


사용자가 타입을 정의할 수 있는 언어들에서 각 타입마다 일대일 대응이 되는 접두어를 할당하는 것은 사실상 힘겨운 일이며, 결국 여러 타입들이 하나의 접두어에 대응되는 중복이 생겨난다. 이러한 중복은 의미상의 오류를 발생시킬 소지가 크고 의미상의 오류는 정말 가장 발견하기 힘든 버그가 되는 경우가 많다.
imays
그래서 제 회사에서는 프로그래머들이 primitive type을 제외하고 접두어에 변수 타입을 안넣는걸 권장하고 있습니다.

CppCheck


에서 발췌.

NCSoft에 다닐 때 들었던 이야기 중에 삼성은 코드품질을 분석하는 툴이 있어서 그 툴로 코드를 분석해서 프로그래머들의 고과점수를 매긴다는 소문이 있었는데 바로 그 소문의 툴이 Coverity Prevent이라는 정적분석툴 소프트웨어 시장 점유율 25%를 차지하고 있는 어마어마한 녀석이다. 물론 가격도 어마어마해서 현재 우리 벤처기업에선 엄두도 내지 못하는 녀석인 것이다.

UnitTest는 특정 행위에 대한 결과가 정확한지 확인하고 객체의 상태 중심적인 테스트인 것이지, 언어적인 측면에서 실행시 발생할 수 있는 잠재적인 오류를 알려주지는 못하기때문에 개인적으로 정적 분석툴에 대해서 관심이 많이 있었는데, Visual Studio에 /analyze라는 옵션이 있어서 컴파일때 정적 분석을 할 수 있다는 것은 알지만, Team Suite버전에 있다라는 씁쓸한 소식과 Tema Suite의 가격을 알아보니 Coverity Prevent보다는 진짜진짜 저렴한 가격이지만 그래도 1300만원대여서 Professional버전을 사용하고 있는 우리의 실정으로는 그것조차 먼 하늘에 떠 있는 별과 같아서 꿈만 꾸었는데, 여기 저기 블로그들을 돌아다니다 알게된 것이 바로 CppCheck라는 오픈소스 정적 분석툴인 것이다. 상용툴에 비해서 아직 부족한 기능이지만 아무 것도 확인하지 않는 것보다는 나을 것 같아서 프로젝트에 도입 결정......

되도록이면 빠르게 업데이트되어서 정말 멋진 녀석으로 성장하길 기도해야겠다. 몰론 항상 바쁘다는 핑계로 오픈소스 프로젝트이지만 기여할 생각은 전혀없다. 솔직히 얘기하면 기여할 능력이 없다라는 것이 정답일 듯......

VUTPP를 사용해보고......

서버 개발을 위해서 개발 환경을 구축하면서, TDD를 위해서 UnitTest++를 쓰려고 Google에서 검색하다가 발견한 Add-in 프로그램인 VUTPP, 지겨운 콘솔 Output이나 XML Reporter에서 벗어나 GUI로 TEST들의 결과와 실패 이유를 볼 수 있다는 엄청난 장점을 가지고 있지만 사용을 하면서 몇몇 가지 단점들을 발견했다.

솔직히, 시간을 내서 OpenSource로 이런 프로그램을 만든 분들의 노고를 생각하면 이런 단점들을 가지고 왈가왈부하는 것이 참 쫌스러운 행동이지만, 그래도 항상 구경꾼이 할말이 더 많은 법이라서......

단점을 적어보자면 다음과 같다.
  • 우선 Project의 설정이 NMake로 되어있으면 PreprocessorDefinitions에서 VUTPP_UNITTEST++ define을 읽어오지 못하지만, 약간의 소스 수정으로 정상적으로 동작하게 고칠 수 있다.
  • 그 다음은 마찬가지로 NMake일 때 Run All, Run Selected가 다 작동하지 않는다. 실행파일 경로를 얻어올 때, bind설정이, application, dynamiclibrary이렇게 두 가지 밖에 없어서 실행파일 경로가 null로 세팅되기 때문이다.
  • 마지막으로 x64 플랫폼으로 컴파일을하면 Bind Failed(Timeout) 오류가 난다. 같은 프로젝트를 win32로 컴파일해서 해보면 정상적으로 동작한다.
개인적으로 Custom BuildTool을 만들어서 사용을 하고 있기때문에, 위의 단점이 엄청크게 느껴지긴 하지만, 누군가를 위해서 이런 공개용 프로그램을 만들어 본 적이 없기때문에, 스스로의 무능력함을 책망할 뿐이다.