페이지를 작성하면서 작성해 나갑니다. TDD 연습중이니 아마 중간 삽질도 예상된다는. ^^; (5시 즈음부터 시작함) 언어는 C++ 로 할 것이고 중간에 STL 중 vector 를 간단하게 이용할겁니다. (자세한 이용법은 나도 모르는 관계로 -_-;) 일단 저는 이 문제를 한번 풀어본 적이 있습니다. 연습삼아서 새로 풀어봅니다. 문제는 암튼 이해했고 (Input 에 대한 Output 이 머릿속에서 어떻게 해야 할지 연결이 된 상태) 가장 간단하게 테스트할 수 있는 방법에 대해 생각해야 하겠군요. Sample Input 을 보니 뒤의 것이 간단해 보이는군요. {{{~cpp 2 1 1 2 100 2 1 1 200 1 1 2 1 2 2 1 2 2 1 0 0 }}} 이를 Target으로 잡으려니, 더 커보이고, 이를 작은 Test 로 나눠봅니다. {{{~cpp 1 1 1 1 1 1 1 1 }}} 여기서 잠시 CppUnit 셋팅을 맞춰놓고. {{{~cpp #include #include #include class TestOne : public CppUnit::TestCase { public: CPPUNIT_TEST_SUITE (TestOne); CPPUNIT_TEST_SUITE_END(); }; int main () { CppUnit::TextUi::TestRunner runner; runner.run("", false); return 0; } }}} 다시 궁리모드 돌입. {{{~cpp 1 1 1 1 1 1 1 1 }}} 에서 테스트 코드에선 인풋 파싱은 일단 미리 생각할 필요가 없으니. {{{~cpp configuration 1,1 로 셋팅 1->1 로 1명 가기 이럴 때, traffic 을 구하면 1명이 나온다. }}} 헉. 30분동안 프린트 하신다고 자리필요하신 분 때문에 지연. -_-; 다시 시작; {{{~cpp class TestOne : public CppUnit::TestCase { public: CPPUNIT_TEST_SUITE (TestOne); CPPUNIT_TEST (test1); CPPUNIT_TEST_SUITE_END(); void test1 () { Configuration* conf = new Configuration (1,1); conf->movePeople (1,1,1); CPPUNIT_ASSERT_EQUAL (1, conf->getTraffic ()); } }; }}} 이에 대한 코드 작성 {{{~cpp class Configuration { int startCity; int endCity; public: Configuration (int startCity, int endCity) { this->startCity = startCity; this->endCity = endCity; } void movePeople (int startCity, int endCity, int people) { } int getTraffic () { return 1; } }; }}} {{{~cpp void test1 () { Configuration* conf = new Configuration (1,1); conf->movePeople(1,1,1); CPPUNIT_ASSERT_EQUAL (1, conf->getTraffic ()); conf->movePeople(1,1,1); CPPUNIT_ASSERT_EQUAL (2, conf->getTraffic ()); } }}} {{{~cpp void movePeople (int startCity, int endCity, int people) { traffic += people; } int getTraffic () { return traffic; } }}} {{{~cpp conf->movePeople(1,1,100); CPPUNIT_ASSERT_EQUAL (102, conf->getTraffic ()); }}} 여기까진 통과..~ test code 를 Refactoring 해봅니다. {{{~cpp void testOneToOneMove () { int dataset [3][3] = {{1,1,1}, {1,1,1}, {1,1,100}}; int expectedSet[3] = {1,2,102}; Configuration* conf = new Configuration (1,1); for (int i=0;i<3;i++) { conf->movePeople(dataset[i][0],dataset[i][1],dataset[i][2]); CPPUNIT_ASSERT_EQUAL (expectedSet[i], conf->getTraffic ()); } delete conf; } }}} 통과한 테스트 {{{~cpp configuration 1,1 로 셋팅 1->1 로 1명 가기 : traffic 1. 1->1 로 1명 더 가기 : traffic 2. 1->1 로 100명 더 가기 : traffic 102. }}} 다음 테스트의 생각 {{{~cpp configuration {1,2},{1,2} 로 셋팅 1->2 로 1명 가기 : traffic 2. }}} {{{~cpp void testOneToTwoMove () { int arrivalCitys[] = {1,2}; int departureCitys[] = {1,2}; Configuration* conf = new Configuration (arrivalCitys, departureCitys); conf->movePeople(1,2,1); CPPUNIT_ASSERT_EQUAL(2, conf->getTraffic()); delete conf; } }}} 에러가 난다. C++ 에서는 터플이 없으므로.. -_- 배열을 넘기는 방법이 있고, vector 를 이용하는 방법이 있습니다. 저번에는 배열로 했기 때문에 이번엔 vector 로 해본다는. ^^; {{{~cpp void testOneToTwoMove () { vector arrivalCitys; vector departureCitys; arrivalCitys.push_back(1); arrivalCitys.push_back(2); departureCitys.push_back(1); departureCitys.push_back(2); Configuration* conf = new Configuration (arrivalCitys, departureCitys); conf->movePeople(1,2,1); CPPUNIT_ASSERT_EQUAL(2, conf->getTraffic()); delete conf; } }}} 컴파일 에러. {{{~cpp --------------------Configuration: AirportSec - Win32 Debug-------------------- Compiling... main.cpp C:\User\reset\AirportSec\main.cpp(57) : error C2664: '__thiscall Configuration::Configuration(int,int)' : cannot convert parameter 1 from 'class std::vector >' to 'int' No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called Error executing cl.exe. AirportSec.exe - 1 error(s), 0 warning(s) }}} 역시, 메인 코드도 수정 필요를 알려준다. {{{~cpp Configuration (vector startCity, vector endCity) { this->startCity = startCity; this->endCity = endCity; this->traffic = 0; } void movePeople (int startCity, int endCity, int people) { traffic += people; } int getTraffic () { return traffic; } }}} 이 경우 testOneToOneMove 가 깨지게 된다. 데이터형이 다르기 때문이다. testOneToOneMove 쪽 테스트 형을 똑같이 작성해준다. {{{~cpp void testOneToOneMove () { int dataset [3][3] = {{1,1,1}, {1,1,1}, {1,1,100}}; int expectedSet[3] = {1,2,102}; vector arrivalCitys; vector depatureCitys; arrivalCitys.push_back(1); depatureCitys.push_back(1); Configuration* conf = new Configuration (arrivalCitys,depatureCitys); }}} 결과 : {{{~cpp 1) test: TestOne::testOneToTwoMove (F) line: 66 C:\User\reset\AirportSec\main.c p equality assertion failed - Expected: 2 - Actual : 1 Press any key to continue }}} 뒤의 테스트가 깨진다. movePeople 의 재정의. {{{~cpp void movePeople (int startCity, int endCity, int people) { traffic += getDistance () * people; } }}} 6:46 밥먹으러 감; 7:50 다시 시작 예정. ^^; ---- getDistance ()의 경우 두 city gate 간의 거리이다. 일단 스텁 코드를 작성해두고, {{{~cpp int getDistance () { return 0; } }}} 다음과 같이 테스트를 다시 작성할 수 있다. {{{~cpp void testGetDistance () { vector arrivalCitys; vector departureCitys; arrivalCitys.push_back(1); departureCitys.push_back(1); Configuration* conf = new Configuration (arrivalCitys, departureCitys); CPPUNIT_ASSERT_EQUAL(1, conf->getDistance(1,1)); } }}} {{{~cpp -------------------Configuration: AirportSec - Win32 Debug-------------------- Compiling... main.cpp C:\User\reset\AirportSec\main.cpp(84) : error C2660: 'getDistance' : function does not take 2 parameters Error executing cl.exe. AirportSec.exe - 1 error(s), 0 warning(s) }}} 컴파일러가 인자 2개짜리 Interface 이기를 요청한다. 요청대로 해주자. {{{~cpp int getDistance (int startCity, int endCity) { return 0; } }}} 그에 따라 다음과 같은 에러가 난다. {{{~cpp --------------------Configuration: AirportSec - Win32 Debug-------------------- Compiling... main.cpp C:\User\reset\AirportSec\main.cpp(24) : error C2660: 'getDistance' : function does not take 0 parameters Error executing cl.exe. AirportSec.exe - 1 error(s), 0 warning(s) }}} 24 라인은 movePeople. {{{~cpp void movePeople (int startCity, int endCity, int people) { traffic += getDistance () * people; } }}} 이 인터페이스도 수정하길 컴파일러가 바라고 있다. 원하는대로 해주자. {{{~cpp void movePeople (int startCity, int endCity, int people) { traffic += getDistance (startCity, endCity) * people; } }}} {{{~cpp 1) test: TestOne::testOneToOneMove (F) line: 54 C:\User\reset\AirportSec\main.cpp equality assertion failed - Expected: 1 - Actual : 0 2) test: TestOne::testOneToTwoMove (F) line: 71 C:\User\reset\AirportSec\main.cpp equality assertion failed - Expected: 2 - Actual : 0 3) test: TestOne::testGetDistance (F) line: 84 C:\User\reset\AirportSec\main.cpp equality assertion failed - Expected: 1 - Actual : 0 }}} 기존의 테스트들이 전부 깨졌다. 기존의 테스트는 getTraffic 와 관련한 부분이고, 우리가 수정한 부분은 getDistance 이다. getDistance 에 촛점을 맞추자. {{{~cpp int getDistance (int startCity, int endCity) { return 0; } }}} 일단은 다음과 같이. 촛점을 맞춰야 할 부분은 testGetDistance. {{{~cpp int getDistance (int startCity, int endCity) { return 1; } }}} {{{~cpp void testGetDistance2() { vector arrivalCitys; vector departureCitys; arrivalCitys.push_back(1); arrivalCitys.push_back(2); departureCitys.push_back(1); departureCitys.push_back(2); Configuration* conf = new Configuration (arrivalCitys, departureCitys); CPPUNIT_ASSERT_EQUAL(2, conf->getDistance(1,2)); delete conf; } }}} getDistance 에 대해 refinement 해주자. {{{~cpp int getDistance (int startCity, int endCity) { return abs (getStartGateIndex(startCity) - getEndGateIndex(endCity)) + 1; } int getStartGateIndex (int startCity) { for (int cityIndex=0; cityIndex < this->startCity.size(); cityIndex++) { if (this->startCity[cityIndex] == startCity) { return cityIndex; } } return -1; } int getEndGateIndex (int endCity) { for (int cityIndex=0; cityIndex < this->endCity.size(); cityIndex++) { if (this->endCity[cityIndex] == endCity) { return cityIndex; } } return -1; } }}} 여기서 Test - Code 의 시간이 꽤 길었다. (9분) 함수 refinement 부분에서 STL 에 있는 find 함수를 함 써먹어 보려고 했다가;; 결국은 평소 하던데로 했다. ^^; Refactoring - 중복없애기. {{{~cpp int find (vector& cities, int city) { for (int cityIndex=0; cityIndex < cities.size(); cityIndex++) { if (cities[cityIndex] == city) { return cityIndex; } } return -1; } }}} 여기서 지금까지 생각한 test 들을 전부 pass 했다. 앞으로 더 해야 할 일이 생각나지 않아서, 한번 실제 메인테스트에 준하는 테스트를 해 보았다. 즉, {{{~cpp 2 1 1 2 100 2 1 1 200 1 1 2 1 2 0 0 }}} 에 대해서 traffic 이 600 이 나오는 것을 확인하는 테스트. {{{~cpp void testRealOne () { vector arrivalCitys; vector departureCitys; arrivalCitys.push_back(1); arrivalCitys.push_back(2); departureCitys.push_back(1); departureCitys.push_back(2); Configuration* conf = new Configuration (arrivalCitys, departureCitys); conf->movePeople(1,2, 100); conf->movePeople(2,1, 200); CPPUNIT_ASSERT_EQUAL(600, conf->getTraffic()); delete conf; } }}} 결과 : ok. Configuration은 실질적인 데이터까지도 트레픽을 계산할 수 있는 수준까지 되었다. 테스트를 좀 더 붙여보자. 좀 더 어려운 경우인 앞단계의 데이터에 대해 해보자. {{{~cpp 1 2 2 10 3 15 2 1 3 10 3 2 1 12 2 20 1 1 2 3 2 3 1 0 0 }}} 일때 traffic 122 가 나와야 한다. {{{~cpp void testRealTwo () { vector arrivalCitys; vector departureCitys; arrivalCitys.push_back(1); arrivalCitys.push_back(2); arrivalCitys.push_back(3); departureCitys.push_back(2); departureCitys.push_back(3); departureCitys.push_back(1); Configuration* conf = new Configuration (arrivalCitys, departureCitys); conf->movePeople(1,2,10); conf->movePeople(1,3,15); conf->movePeople(2,3,10); conf->movePeople(3,1,12); conf->movePeople(3,2,20); CPPUNIT_ASSERT_EQUAL(122, conf->getTraffic()); delete conf; } }}} pass 되었다. 아무래도 한번 미리 짜본 프로그램이여서 그런지 초반에 일반화된 것이 아닐까 하는 생각이 든다. Refactoring 하기 전 현재 소스. {{{~cpp #include #include #include #include #include using namespace std; class Configuration { vector startCity; vector endCity; int traffic; public: Configuration (vector startCity, vector endCity) { this->startCity = startCity; this->endCity = endCity; this->traffic = 0; } int find (vector& cities, int city) { for (int cityIndex=0; cityIndex < cities.size(); cityIndex++) { if (cities[cityIndex] == city) { return cityIndex; } } return -1; } int getStartGateIndex (int startCity) { return find (this->startCity, startCity); } int getEndGateIndex (int endCity) { return find (this->endCity, endCity); } int getDistance (int startCity, int endCity) { return abs (getStartGateIndex(startCity) - getEndGateIndex(endCity)) + 1; } void movePeople (int startCity, int endCity, int people) { this->traffic += getDistance (startCity, endCity) * people; } int getTraffic () { return this->traffic; } }; class TestOne : public CppUnit::TestCase { public: CPPUNIT_TEST_SUITE (TestOne); CPPUNIT_TEST (testOneToOneMove); CPPUNIT_TEST (testOneToTwoMove); CPPUNIT_TEST (testGetDistance); CPPUNIT_TEST (testGetDistance2); CPPUNIT_TEST (testRealOne); CPPUNIT_TEST (testRealTwo); CPPUNIT_TEST_SUITE_END(); void testOneToOneMove () { int dataset [3][3] = {{1,1,1}, {1,1,1}, {1,1,100}}; int expectedSet[3] = {1,2,102}; vector arrivalCitys; vector depatureCitys; arrivalCitys.push_back(1); depatureCitys.push_back(1); Configuration* conf = new Configuration (arrivalCitys,depatureCitys); for (int i=0;i<3;i++) { conf->movePeople(dataset[i][0],dataset[i][1],dataset[i][2]); CPPUNIT_ASSERT_EQUAL (expectedSet[i], conf->getTraffic ()); } delete conf; } void testOneToTwoMove () { vector arrivalCitys; vector departureCitys; arrivalCitys.push_back(1); arrivalCitys.push_back(2); departureCitys.push_back(1); departureCitys.push_back(2); Configuration* conf = new Configuration (arrivalCitys, departureCitys); conf->movePeople(1,2,1); CPPUNIT_ASSERT_EQUAL(2, conf->getTraffic()); delete conf; } void testGetDistance () { vector arrivalCitys; vector departureCitys; arrivalCitys.push_back(1); departureCitys.push_back(1); Configuration* conf = new Configuration (arrivalCitys, departureCitys); CPPUNIT_ASSERT_EQUAL(1, conf->getDistance(1,1)); delete conf; } void testGetDistance2() { vector arrivalCitys; vector departureCitys; arrivalCitys.push_back(1); arrivalCitys.push_back(2); departureCitys.push_back(1); departureCitys.push_back(2); Configuration* conf = new Configuration (arrivalCitys, departureCitys); CPPUNIT_ASSERT_EQUAL(2, conf->getDistance(1,2)); delete conf; } void testRealOne () { vector arrivalCitys; vector departureCitys; arrivalCitys.push_back(1); arrivalCitys.push_back(2); departureCitys.push_back(1); departureCitys.push_back(2); Configuration* conf = new Configuration (arrivalCitys, departureCitys); conf->movePeople(1,2, 100); conf->movePeople(2,1, 200); CPPUNIT_ASSERT_EQUAL(600, conf->getTraffic()); delete conf; } void testRealTwo () { vector arrivalCitys; vector departureCitys; arrivalCitys.push_back(1); arrivalCitys.push_back(2); arrivalCitys.push_back(3); departureCitys.push_back(2); departureCitys.push_back(3); departureCitys.push_back(1); Configuration* conf = new Configuration (arrivalCitys, departureCitys); conf->movePeople(1,2,10); conf->movePeople(1,3,15); conf->movePeople(2,3,10); conf->movePeople(3,1,12); conf->movePeople(3,2,20); CPPUNIT_ASSERT_EQUAL(122, conf->getTraffic()); delete conf; } }; int main () { CppUnit::TextUi::TestRunner runner; runner.addTest (TestOne::suite()); runner.run("", false); return 0; } }}} 테스트 코딩 Refactoring - 으.. 여전히 시간이 많이 걸린다. 주로 중복을 없애는 방향으로 접근. {{{~cpp #ifndef _CONFIGURATION_H_ #define _CONFIGURATION_H_ #include using namespace std; class Configuration { vector startCity; vector endCity; int traffic; public: Configuration (vector startCity, vector endCity) { this->startCity = startCity; this->endCity = endCity; this->traffic = 0; } int find (vector& cities, int city) { for (int cityIndex=0; cityIndex < cities.size(); cityIndex++) { if (cities[cityIndex] == city) { return cityIndex; } } return -1; } int getStartGateIndex (int startCity) { return find (this->startCity, startCity); } int getEndGateIndex (int endCity) { return find (this->endCity, endCity); } int getDistance (int startCity, int endCity) { return abs (getStartGateIndex(startCity) - getEndGateIndex(endCity)) + 1; } void movePeople (int startCity, int endCity, int people) { this->traffic += getDistance (startCity, endCity) * people; } int getTraffic () { return this->traffic; } }; #endif }}} history 를 보니 30분정도 걸렸군요. 흠.. 그러다가 보니, 테스트 코드에서 자주 중복이 나타나는 부분이 눈에 띤다. {{{~cpp int arrivalData[] = {1,2}; int departureData[] = {1,2}; conf = new Configuration (arrivalCitys, departureCitys); }}} 식으로 설정되는 Configuration 부분. setUp 부분 묶어서 Configuration 에 대한 테스트를 두개로 묶기로 했다. {{{~cpp #ifndef _TEST_CONFIGURATION_H_ #define _TEST_CONFIGURATION_H_ #include #include #include using namespace std; void intVectorInit (vector& vec, int* intList, int count) { for (int i=0;imovePeople(moveDataSet[i][0], moveDataSet[i][1], moveDataSet[i][2]); } } class TestConfigurationBasic : public CppUnit::TestCase { CPPUNIT_TEST_SUITE (TestConfigurationBasic); CPPUNIT_TEST (testOneToOneMove); CPPUNIT_TEST (testGetDistance); CPPUNIT_TEST_SUITE_END(); public: Configuration* conf; vector arrivalCitys; vector departureCitys; void setUp () { conf = NULL; } void tearDown () { if (conf) delete conf; arrivalCitys.clear(); departureCitys.clear(); } void testOneToOneMove () { int moveDataSet [3][3] = {{1,1,1}, {1,1,1}, {1,1,100}}; int expectedSet[3] = {1,2,102}; arrivalCitys.push_back(1); departureCitys.push_back(1); conf = new Configuration (arrivalCitys,departureCitys); for (int i=0;i<3;i++) { conf->movePeople(moveDataSet[i][0],moveDataSet[i][1],moveDataSet[i][2]); CPPUNIT_ASSERT_EQUAL (expectedSet[i], conf->getTraffic ()); } } void testGetDistance () { vector arrivalCitys; vector departureCitys; arrivalCitys.push_back(1); departureCitys.push_back(1); conf = new Configuration (arrivalCitys, departureCitys); CPPUNIT_ASSERT_EQUAL(1, conf->getDistance(1,1)); } }; class TestConfigurationCityTwo : public CppUnit::TestCase { CPPUNIT_TEST_SUITE (TestConfigurationCityTwo); CPPUNIT_TEST (testOneToTwoMove); CPPUNIT_TEST (testGetDistance2); CPPUNIT_TEST (testRealOne); CPPUNIT_TEST_SUITE_END(); public: Configuration* conf; vector arrivalCitys; vector departureCitys; void setUp () { conf = NULL; int arrivalData[] = {1,2}; int departureData[] = {1,2}; intVectorInit (arrivalCitys, arrivalData, 2); intVectorInit (departureCitys, departureData, 2); } void tearDown() { if (conf) delete conf; arrivalCitys.clear(); departureCitys.clear(); } void testOneToTwoMove () { conf = new Configuration (arrivalCitys, departureCitys); conf->movePeople(1,2,1); CPPUNIT_ASSERT_EQUAL(2, conf->getTraffic()); } void testGetDistance2() { conf = new Configuration (arrivalCitys, departureCitys); CPPUNIT_ASSERT_EQUAL(2, conf->getDistance(1,2)); } void testRealOne () { int moveDataSet[2][3] = {{1,2,100}, {2,1,200}}; conf = new Configuration (arrivalCitys, departureCitys); movePeople (conf, moveDataSet, 2); CPPUNIT_ASSERT_EQUAL(600, conf->getTraffic()); } }; class TestConfigurationCityThree : public CppUnit::TestCase { CPPUNIT_TEST_SUITE(TestConfigurationCityThree); CPPUNIT_TEST (testRealTwo); CPPUNIT_TEST_SUITE_END(); public: Configuration* conf; vector arrivalCitys; vector departureCitys; void setUp () { conf = NULL; } void tearDown () { if (conf) delete conf; arrivalCitys.clear(); departureCitys.clear(); } void testRealTwo () { int arrivalData[] = {1,2,3}; int departureData[] = {2,3,1}; int moveDataSet[5][3] = {{1,2,10}, {1,3,15}, {2,3,10}, {3,1,12}, {3,2,20}}; intVectorInit (arrivalCitys, arrivalData, 3); intVectorInit (departureCitys, departureData, 3); conf = new Configuration (arrivalCitys, departureCitys); movePeople (conf, moveDataSet, 5); CPPUNIT_ASSERT_EQUAL(122, conf->getTraffic()); } }; #endif }}} 근데, Refactoring 에 대해서만 1시간을 쓴 것 같다. 그것도 메인 코드인 Configuration 클래스 보단, Test 코드에 대한 Refactoring 이 주가 된 것 같다. 실질적인 실용성을 볼때, 메인 코드에 대한 Refactoring 위주로 나가는 것이 좋을 것 같다. (깨진 Test 는 주로 삭제하는 스타일로 가고..) Configuration 하나에 대해서는 된 것 같고. 또 테스트 들어갈 것이 없을까... 생각하던중, 이제는 여러개의 데이터가 들어가야겠다는 생각을 하게 되었다. 즉, Configuration 이 2개인 경우에 대해서. Configuration 이 2개인 경우에 대해서. 이 Configuration 을 가지고 있는 것을 Airport 라고 상정짓도록 하겠다. Airport 는 Configuration 을 등록할 수 있으며, 각각의 Configuration 경우에 대한 Traffic 들을 각 Configuration 에게 물어봄으로서 계산된 Traffic 들을 알 수 있다. 간단한 두번째의 경우 예를 먼저 든다면. {{{~cpp 1 1 2 100 2 1 1 200 1 1 2 1 2 2 1 2 2 1 0 0 }}} 각 경우에 대해 첫번째 traffic 은 600이, 두번째 traffic 은 300 이 나와야 한다. {{{~cpp class TestAirport : public CppUnit::TestCase { CPPUNIT_TEST_SUITE (TestAirport); CPPUNIT_TEST (testOne); CPPUNIT_TEST_SUITE_END(); public: Configuration* conf1; Configuration* conf2; vector arrivalCitys; vector departureCitys; vector arrivalCitys2; vector departureCitys2; void setUp () { int arrivalData[] = {1,2}; int departureData[] = {1,2}; intVectorInit (arrivalCitys, arrivalData, 2); intVectorInit (departureCitys, departureData, 2); conf1 = new Configuration (arrivalCitys, departureCitys); int arrivalData2[] = {1,2}; int departureData2[] = {2,1}; intVectorInit (arrivalCitys2, arrivalData, 2); intVectorInit (departureCitys2, departureData, 2); conf2 = new Configuration (arrivalCitys2, departureCitys2); } void tearDown () { delete conf1; delete conf2; arrivalCitys.clear(); departureCitys.clear(); arrivalCitys2.clear(); departureCitys2.clear(); } void testOne () { Airport* airport = new Airport(); airport->registerConfiguration (conf1); airport->registerConfiguration (conf2); airport->movePeople (1,2,100); airport->movePeople (2,1,200); CPPUNIT_ASSERT_EQUAL (600, airport->getTraffic(0)); CPPUNIT_ASSERT_EQUAL (300, airport->getTraffic(1)); } }; }}} airport 관련 코드 구현. {{{~cpp void movePeople (int startCity, int endCity, int people) { for (int i=0;i< this->configurations.size();i++) { this->configurations[i]->movePeople(startCity, endCity, people); } } }}} 결과 : {{{~cpp 1) test: TestAirport::testOne (F) line: 72 c:\user\reset\airportsec\testairport.h equality assertion failed - Expected: 300 - Actual : 600 }}} 왜 두번째 configuration 의 경우에 대해서 에러일까? 다시 configuration 으로; 테스트를 더 추가해 보았다. {{{~cpp void testGetDistance2to1() { CPPUNIT_ASSERT_EQUAL(2, conf->getDistance(2,1)); } }}} 멀쩡하다. 그래서, Configuration 에 대한 테스트를 더 작성하였다. {{{~cpp void testTwoToOneMove () { int arrivalData[] = {1,2}; int departureData[] = {2,1}; intVectorInit (arrivalCitys, arrivalData, 2); intVectorInit (departureCitys, departureData, 2); conf = new Configuration (arrivalCitys, departureCitys); conf->movePeople(1,2,100); CPPUNIT_ASSERT_EQUAL(100, conf->getTraffic()); } }}} {{{~cpp // 추가된 테스트 conf->movePeople(2,1,200); CPPUNIT_ASSERT_EQUAL(300, conf->getTraffic()); }}} 작동을 잘 한다; 문제는 이제 Airport 쪽으로 축소되는 듯 하다. {{{~cpp // 문제 발견! - AirportTest::setUp() int arrivalData2[] = {1,2}; int departureData2[] = {2,1}; intVectorInit (arrivalCitys2, arrivalData, 2); // <-- arrivalData2 로 초기화되어야 한다. intVectorInit (departureCitys2, departureData, 2); // 역시 또한; }}} {{{~cpp ......... OK (9 tests) }}} 다른 테스트에 대해서도 해보자. {{{~cpp void testGetTraffics2 () { int arrivalData[] = {1,2,3}; int departureData[] = {2,3,1}; intVectorInit (arrivalCitys, arrivalData, 3); intVectorInit (departureCitys, departureData, 3); conf1 = new Configuration (arrivalCitys, departureCitys); int arrivalData2[] = {2,3,1}; int departureData2[] = {3,2,1}; intVectorInit (arrivalCitys2, arrivalData2, 3); intVectorInit (departureCitys2, departureData2, 3); conf2 = new Configuration (arrivalCitys2, departureCitys2); Airport* airport = new Airport(); airport->registerConfiguration (conf1); airport->registerConfiguration (conf2); airport->movePeople (1,2,10); airport->movePeople (1,3,15); airport->movePeople (2,3,10); airport->movePeople (3,1,12); airport->movePeople (3,2,20); CPPUNIT_ASSERT_EQUAL (122, airport->getTraffic(0)); CPPUNIT_ASSERT_EQUAL (119, airport->getTraffic(1)); delete airport; } }}} Sort 결과 테스트. {{{~cpp void testSortedResult () { int arrivalData[] = {1,2,3}; int departureData[] = {2,3,1}; intVectorInit (arrivalCitys, arrivalData, 3); intVectorInit (departureCitys, departureData, 3); conf1 = new Configuration (arrivalCitys, departureCitys); int arrivalData2[] = {2,3,1}; int departureData2[] = {3,2,1}; intVectorInit (arrivalCitys2, arrivalData2, 3); intVectorInit (departureCitys2, departureData2, 3); conf2 = new Configuration (arrivalCitys2, departureCitys2); Airport* airport = new Airport(); airport->registerConfiguration (conf1); airport->registerConfiguration (conf2); airport->movePeople (1,2,10); airport->movePeople (1,3,15); airport->movePeople (2,3,10); airport->movePeople (3,1,12); airport->movePeople (3,2,20); vector configurations = airport->getSortedResult (); CPPUNIT_ASSERT_EQUAL (119, configurations[0]->getTraffic()); CPPUNIT_ASSERT_EQUAL (122, configurations[1]->getTraffic()); CPPUNIT_ASSERT_EQUAL (122, airport->getTraffic(0)); CPPUNIT_ASSERT_EQUAL (119, airport->getTraffic(1)); delete airport; } }}}