'cppunit'에 해당되는 글 2건

  1. 2011/05/24 VS2008에서 CppUnit 설정
  2. 2007/03/19 Crash Course in using CppUnit
sw2011/05/24 14:06
CppUnit을 vs2008에서 설정하는 방법을 보여주는 동영상입니다.
좀 많이 버벅 대는것 같아도 기본 설정을 하기 위한 이해를 돕기에는 아주 좋은것 같습니다..

http://vimeo.com/10921708

 
 
Posted by redef
TAG cppunit

댓글을 달아 주세요

sw2007/03/19 11:44

http://www.comp.nus.edu.sg/~cs3214s/tools/cppunitVC.html
Crash Course in using CppUnit

Introduction

이문서에서는 CppUnit이라 불리는 테스팅 프레임워크에 대해 소개할것이다.
CppUnit은 Erich Gamma와 Kent Beck에 의해 개발된 테스팅 프레임워크 JUnit의 C++ port이다.
Michael Feathers에 의해 ported 되었다.
CppUnit의 주된 목적은 C++프로그램의 unit 테스트 하는것을 개발자들에게 제공하기 위한것이다.
학생들이 C++ 언어 프로젝트에서 사용하면, CppUnit을 테스트하기위해 광범위하게 사용하길 바란다.
프로젝트의 질적향상을 위해 꼭 필요한 신뢰성이란것을 생각할수 있다.

CppUnit은 그러한 것을 달성하는데 도움을 줄수 있다.
이 문서는 JUnit 가이드의 “port”를 고려하여 작성하였다.
특히, MS Visual C++ 6.0에서 CppUnit의 사용에 대해 말할 것이다.
JUnit 가이드에서 처럼 단지 시작하는데 최소한의 것만을 보일것이다.
처음에는 다음 섹션에서 우선 CppUnit을 인스톨하는것에 대해 진행할것이며, 이어서 예제 프로그램을 사용하여 CppUnit을 어떻게 사용하는지에 대해 설명할것이다.
다음으로, 프로젝트와 테스트 코드의 구성에 대해 예기하며, 유용한 레퍼런스와 문서로 마무리를 할것이다.

------------------------------------------------------------------------

Installing CppUnit

CppUnit의 인스톨은 대충 다음과 같이 할 수 있다.

1. CppUnit을 다운로드 해서 압축을 원하는 위치에 푼다.

이 문서의 나머지에서 나는 C:\에 압축을 푼것으로 간주하고 앞으로 그 소스파일의 위치를 C:\CppUnit 으로 알겠다.

2. CppUnit 인스톨을 위한 작업들이다 :

Visual C++ IDE를 시작한다.
File->Open 을 선택한다.
“Workspaces”의 “Files of type”을 변경한다.
C:\CppUnit\ms\culib 디렉토리로 가서 culib.dsw 워크스페이스를 연다.
사용자 삽입 이미지




















다음으로 Build->Rebuild All을 선택하여 culib.lib 라이브러리를 만든다.

2. File->Open을 다시 선택하여 C\CppUnit\ms\TestRunner 디렉토리로 이동하여 TestRunner.dsw 워크스페이스를 연다.
비슷하게, Build->Rebuild All을 선택하여 TestRunner.dll을 만든다.
3.File->Open을 선택하고 C:\CppUnit\ms\HosApp 디렉토리로 이동하여 HostApp.dsw 워크스페이스를 연다.
이후에, Build->Rebuild All을 선택하여 application을 컴파일한다.
Build->Execute HostApp.exe를 선택하여 application을 실행한다.
TestRunner GUI가 나타날것이다.
Run버튼을 클릭해야만 테스트들이 실행될것이다.
사용자 삽입 이미지


약간의 failure들과 error들이 있을것이다.
TestRunner 창을 닫는다.
다른 창이 뜰것이다.
닫는다.
CppUnit이 이제 잘 인스톨되었다.

3.작성하는 테스트 프로그램에서 그래피컬한 인터페이스를 엮기웨해서는 꽤복잡하기 때는에 단지 CppUnit의 텍스트기반의 인터페이스를 어떻게 사용하는가에 대해만 설명 할것이다.
그래피컬한 버전을 실행하는데 흥미가 있다면 나에게 이메일을 보내길 바란다.
텍스트기반 인터페이스의 CppUnit 라이브러리를 사용하기 위해서 재컴파일 해야한다.
우선, File->Open 을 선택하고 C:\CppUnit\ms\culib 로 이동하여 culib.dsw 워크스페이스를 다시 연다.
다음으로, Project->Settings를 선택한다.
새로운 다이얼로그가 나타날것이다.
“Microsoft Foundation Classes” 머릿말 아래에 “Use MFC in a Shared DLL” 대신에 “Not Using MFC”를 선택한다.
사용자 삽입 이미지























다음으로, 텍스트 인터페이스를 실행하기위해 파일들을 추가한다.
Project->Add To Project->Files를 선택하고 C:\CppUnit\test\testui 디렉토리로 이동하고 TextTestResult.h와 TextTestResult.cpp를 추가한다.
한가지 이상의 세팅을 변경해야 한다.
Project->Settings에서 C/C++탭을 선택한다.
카테고리 드랍박스의 아래에서 Preprocessor를 선택한다.
“Additional include directories”의 텍스트박스에 “C:\CppUnit\test\framework” 으로 적는다.
사용자 삽입 이미지























마지막으로, Build->Rebuild All을 선택하여 CppUnit 라이브러리를 만든다.

-----------------------------------------------------------------------

Using CppUnit
Overview
여기에서, CppUnit을 어떻게 사용할지에 대한 일반적인 과정에 대한 내용을 제공할 것이다.
다음 섹션에서 예제를 사용해 key steps를 설명할것이다.
나의 충고는 걸러낼거 걸러내고 이부분은 빠르게 훑어볼것이다.
그리고 너는 예제를 통한 다음섹션으로 가지만 전체 사진을 얻기위해 종종 이섹션으로 다시 돌아올것이다.
건방지지만 테스트를 원하는 클래스를 Parser라 부르겠다.
이 클래스를 테스트하기위한 CppUnit 프레임워크를 사용하기 위한 일반적인 과정은 아래와 같다.

1.Parser 클래스로 test를 위한 클래스를 작성한다.(앞으로 TestParser라 부를다.)
이 클래스는 CppUnit 프레임워크에 정의되어 있는 TestCase 클래스의 상속을 받아야만 한다.
2.이 클래스의 생성자를 만들어서 테스트를 위한 클래스의 설정을 위한 파라미터로 이름을 넘겨준다.
3.fixture를 만든다.
test fixture는 테스팅을 하는동안 사용하길 원하는 객체와 동일하게 설정된다.
예제로, 분석을위한 Parser용 샘플 소스파일을 만들어 볼것이다.
CppUnit은 fixture를 관리하기위한 setUp과 tearDown 메소드를 제공한다.
그런까닭에, 소스파일을 열기위해 setUp으로 파일객체를 만들고 tearDown 메소드로 리소스를 release 할 수있다.
‘test’를 실행할때마다 setUp과 tearDown을 호출한다는것은 중요하다.
4.test 클래스에서 메소드를 이용한 구현으로 각 ‘test’를 행할것이다.
예를 들어, 정확한 토큰을 분리분석을위한 test를 하기 원하면 testGetToken을 호출하여 메소드를 구현할수 있다.
test 메소드의 collection은 구현하는 test suite 형식이다.
5.테스트 메소드를 만들어서 결과와 test 실행의 결과를 비교하기위해 CppUnit에서는 assertion 메카니즘을 제공한다.
시각적으로 결과를 확인하여 시간을 절약하는것뿐만아니라 반복적인 테스트를 만드는것도 가능하다.
6.마지막으로, textual 버전의 TestRunner Tool을 사용하여 결과를 수집, 테스트할수 있다.
각 test를 실행함으로서, CppUnit은 예외가 나타나는지 test가 실패하는지, 실행이 성공하는지의 feedback을 제공한다
Example
이 섹션에서 예제를 사용하여 CppUnit을 어떻게 사용하는지 설명할것이다.
첫째로, Visual C++ IDE를 실행해야 한다.
Select File->New. 샐운 창이 나타난다.
Projects 탭 아래의 “Win32 Console Application”을 선택한다.
Location 아래에 “C:\CS3214s” 를 입력한다.
이 디렉토리에 이 프로젝트의 모든 파일을 저장할것이다.( 필요하다면 디렉토리를 만든다.)
다음으로, 프로젝트의 이름을 준다.
Project Name 아래에 “tutorial” 을 입력한다.
사용자 삽입 이미지
























Console Application 종류를 만들기위해서 “An emtpy project”를 선택하고 Finish 버튼을 클릭할 것이다.
새로운 프로젝트 정보를 창으로 보여줄것이다.
Ok 버튼을 클릭하여 그것을 닫는다.
사용자 삽입 이미지























다음으로, 예제에서 사용할 클래스를 만들어야 한다.
사용하는 에디터로 코드를 입력하여 C:\CS214s\tutorial에 위치시켜서 tutorial 프로젝트에 IDE(Project->Add To Project->Files)로 추가시키거나, IDE를 사용하여 필요한 파일을 만들수 있다.
두 클래스들(.h와 .cpp)가 무엇을 하는것인지 다음예제로 잠시보겠다:

Course.h
#ifndef Course_h
#define Course_h

#include

class Course {
public:
// Default constructor
Course();

// Constructor
Course(std::string nm, int gr);

// method to get the name of the course
std::string getCourseName();

// method to get the grade of the course
int getCourseGrade();

private:
std::string course_name; // name of this course
int grade; // grade of this course
};
#endif

Course.cpp
#include “Course.h”

// default constructor
Course::Course() {
course_name = “”;
grade = -1;
}

// constructor
Course::Course(std::string nm, int gr):course_name(nm) {
grade = gr;
}

// method to get the name of the course
std::string Course::getCourseName() { return course_name; }

// method to get the grade of the course
int Course::getCourseGrade() { return grade; }

Student.h
#ifndef Student_h
#define Student_h

#include
#include
#include “Course.h”

const int MAXNUM = 20; // Maximum number of courses allowed per student

class Student {
public :
// Constructor
Student(std::string nm, std::string no);

// Method to return student’s name
std::string getStuName();

// Method to return student’s number
std::string getStuNumber();

// Method to assign a grade to a course
void assignGrade(std::string co, int gr);

// Method to return the grade of a course
int getGrade(std::string co);
private:
std::string name; // name of the student
std::string number; // the student’s number
Course course_grades[MAXNUM]; // courses taken by student
int no_of_courses; // the current number of courses taken
};
#endif

Student.cpp
#include “Student.h”

// Constructor
Student::Student(std::string nm, std::string no):name(nm), number(no) {
no_of_courses = 0;
}

// Method to return student’s name
std::string Student::getStuName() { return name; }

// Method to return student’s number
std::string Student::getStuNumber() { return number; }

// Method to assign a grade to course
void Student::assignGrade(std::string co, int gr) {
// check whether the maximum number of courses have been taken
if (no_of_courses == MAXNUM) {
std::cout < < "You have exceeded the maximum number of courses !\n";
return;
}
// create a new course
Course c(co, gr);
course_grades[no_of_courses++] = c;
}

// Method to return the grade of a course
int Student::getGrade(std::string co) {
int i = 0;

while (i < no_of_courses) {
//check if course name the same as co
if (course_grades[i].getCourseName() == co)
return (course_grades[i].getCourseGrade());
i++;
}
return(-1);
}

기본적인 이 두 클래스(Course와 Student)이다.
각 Course는 이름을 포함한다.
CS3214s와 정수 grade는 0부터 100 범위의 값을 갖는다.
학생각자는 이름을 갖고, 순번에다가 학년별 코스가 있다.
getGrade 메소드로 정규 코스의 학년을 받아서 assignGrade 메소드로 정규코스의 학생점수를 학년에 추가할수 있다.
다음으로, test 클래스를 만든다.
아래와 같이 test 파일들에 Student 클래스(TestStudent.h와 TestStudent.cpp라 부른다)를 작성한다.

TestStudent.h
#ifndef TestStudent_h
#define TestStudent_h

#include
#include

// Note 1
#include “TestCase.h”
#include “TestSuite.h”
#include “TestCaller.h”

#include “Student.h”

class StudentTestCase : public TestCase { // Note 2
public:
// constructor - Note 3
StudentTestCase(std::string name) : TestCase(name) {}

// method to test the constructor
void testConstructor();

// method to test the assigning and retrieval of grades
void testAssignAndRetrieveGrades();

// method to create a suite of tests
static Test *suite ();
};
#endif

TestStudent.cpp
#include “TestStudent.h”

// method to test the constructor
void StudentTestCase::testConstructor() { // Note 4
// create a student object
Student stu(”Tan Meng Chee”, “94-1111B-13″);

// check that the object is constructed correctly - Note 5
std::string student_name = stu.getStuName();
assert(student_name == “Tan Meng Chee”);
std::string student_number = stu.getStuNumber();
assert(student_number == “94-1111B-13″);
}

// method to test the assigning and retrieval of grades
void StudentTestCase::testAssignAndRetrieveGrades() {
// create a student
Student stu(”Jimmy”, “946302B”);

// assign a few grades to this student
stu.assignGrade(”cs2102″, 60);
stu.assignGrade(”cs2103″, 70);
stu.assignGrade(”cs3214s”, 80);

// verify that the assignment is correct - Note 6
assertEquals(60, stu.getGrade(”cs2102″));
assertEquals(70, stu.getGrade(”cs2103″));

// attempt to retrieve a course that does not exist
assertEquals(-1, stu.getGrade(”cs21002″));
}

// method to create a suite of tests - Note 7
Test *StudentTestCase::suite () {
TestSuite *testSuite = new TestSuite (”StudentTestCase”);

// add the tests
testSuite->addTest (new TestCaller
(”testConstructor”, &StudentTestCase::testConstructor));
testSuite->addTest (new TestCaller
(”testAssignAndRetrieveGrades”,
&StudentTestCase::testAssignAndRetrieveGrades));
return testSuite;
}

앞의 코드의 Note들을 보자:

Note 1
세개의 작성한 test 클래스들의 헤더파일인TestCase.h, TestSuite.h와 TestCaller.h 을 포함시켜야 하는것을 기억하자.
Note 2
모든 test 클래스는 TestCase 클래스를 상속받아서 작성해야만 한다.
Note 3
이 생성자는 완벽한 표준이다. 만드는 모든 test 클래스에서 똑같이 잘라붙여야만 한다.
Note 4
이 예제는 Student 클래스의 하나의 메소드를 테스트하기 위해 작성한 메소드이다.
예를 들어, 생성자의 테스트이다.
Note 5
사용하게될 가장 일반적인 구문의 하나가 assert구문이다.
값은 true혹은 false값중의 하나를 결정해야하는 boolean 표현이다.
Note 6
assertEquals 메소드는 테스트가 성공인지 실패인지를 확인하는데에 사용할수 있다.
두개의 값을 갖고 그것들을 비교한다.
값이 다르다면, 테스트가 실패가 되어 예외가 발생하게 될것이다.
Note 7
이 클래스 메소드는 테스트 suite 들을 모아놓곤한다.
이것은 표준이다.
잘라서 붙여서, 필요한데로 suit들을 바꾼다.
일반적으로, test 클래스의 이름을 StudentTestCase로 바꾸고 test 메소드의 값들을 대신할 것들로 바꾼다.
마지막으로 TestRunner.cpp 파일을 C:\CS3214s\CppUnit\test\textui에서 C:\CS3214s\tutorial로 복사한다.
tutorial 프로젝트에 파일을 추가하고 아래와 같이 바꾼다 :

change:
#include “ExampleTestCase.h”
to:
#include “TestStudent.h”

and

change:
runner.addTest (”ExampleTestCase”, ExampleTestCase::suite ());
to:
runner.addTest (”StudentTestCase”, StudentTestCase::suite ());

테스트하기위한 test 클래스를 다르게 작성했다면, TestRunner.cpp를 사용하려는 용도에 맞게 수정해야 한다.

이제 테스트들을 컴파일하고 실행할 준비가 되었다.
그전에 프로젝트의 셋팅을 만들어줘야 한다.
Project->Settings 에서 C/C++ 탭을 선택한다.
Under the Category dropbox, select Preprocessor.
Category 드랍박스에서 Preprocessor를 선택한다.
Put “C:\CppUnit\test\framework, C:\CppUnit\test\textui” in the “Additional include directories” textbox.
“Additional include directories”의 텍스트박스에서 “C:\CppUnit\test\framework, C:\CppUnit\textui” 를 입력한다.
사용자 삽입 이미지























마지막으로 Link 탭을 클릭하여 “Object/library modules”의 텍스트박스에서 “C:\CppUnit\ms\culib\Debug\culib.lib”를 추가한다.
Ok를 클릭하면 이제 테스트를 하기위한 준비가 되었다.
사용자 삽입 이미지






















Build->Rebuild All을 선택해 컴파일을 시작한다.
몇개의 warning들이 있을거지만 게의치 안아도 되는 것들이다.
마지막으로, 도스창을 열고 C:\CS3214s\tutorial\Debug를 연다.
Type

tutorial StudentTestCase

만약에 아래와 같은 출력이라면 unit 테스트에 완벽하게 성공한것이다.
사용자 삽입 이미지


Exercise
CppUnit을 배우기위한 최상의 방법은 사용해보는것이다.
그래서, 실전연습을 직접해볼수 있는 작은 예제를 마련했다.
학생이 모든 코스에서 발생하는 점수의 평균을 구해 메소드를 추가하여 Student 클래스를 확장해보자
Student.h와 Student.cpp에 아래와 같이 코드를 추가할수 있다:

// In Student.h under public
// Method to return the average grade
float findAveGrade();

// In Student.cpp
// Method to return the average grade
float Student::findAveGrade() {
float sum = 0.0, average;

// sum up the marks in all the courses
for (int i = 0; i < no_of_courses; i++)
sum += course_grades[i].getCourseGrade();
average = sum / no_of_courses;
return(average);
}

테스트를 위해 새롭게 만들어진 메소드를 StudentTestCase 클래스의 메소드로 작성하는 일을 하면된다.
CppUnit을 어떻게 사용하는지 실제로 알수 있게 한다.

--------------------------------------------------------------------------------

Organizing the project code
프로젝트가 반복되면서 소스코드의 양이 증가하는것을 발견하게 될것이다.
적당하게 구성하지 못한다면, 그 디렉토리는 온통 소스파일로 넘칠것이다. 그것은 다른 멤버들에 의해 작성된 비슷한 코드혹은 올바른 코드를 찾는것이 힘들게된다.
MS Visual C++에서 폴더들안에 클래스들을 구성할수 있다.
이것은 맴버들 각자를 구분할수 있는 효과적인 방법이다.
예를 들어, SPA의 다른 부분의 코드를 저장하기 위한 폴더를 만들수 있다.

pkb
parser
extractor
preprocessor
evaluator
projector
Organizing the test code

가이드라인을 따라서 "코드약간, 테스트 약간, 코드약간, 테스트 약간..."하면, 곧 프로젝트 진행중에 급속하게 증가되는 테스트 코드를 발견하게 된다.
테스트 코드를 동일한 디렉토리나 테스트하려는 코드가 위치하는 디렉토리의 아래디렉토리에 위치시킬수 있다.
중요한것은 아무곳에서나 테스트코드를 산재시켜서는 안된다. - 테스트 하는 처리를 효율적으로 재사용하기위해서이다.

--------------------------------------------------------------------------------

References
불행하게도, CppUnit에 관한 문서가 많지 않다.
대신에 CppUnit을 적용하고 전반적인 프레임워크를 이해하기위해 JUnit 가이드를 읽을수 있다
기억해라, CppUnit의 가능성을 최고로 올리기 위해서 더많이 읽고 더많은 실험을 통해 내것으로 만들 필요가 있다.
만약에 필요에 의해서 CppUnit의 소스를 읽는다면 도움이 될것들이다.

CppUnit Cookbook - doc 서브디렉토리에 있다.
이 설명서에는 CppUnit에 대해 훌륭히 설명이 되어있다.
이 가이드외에 더 많은 문서가 필요하다면 한가지 더있다.
다른 레퍼런스로 JUnit 가이드가 있다.
Posted by redef
TAG C, cppunit

댓글을 달아 주세요