return m_amount; }
std::string getCurrency() const { return m_currency; } private: double m_amount; std::string m_currency; }; #endif
Ở tập tin MoneyTest.cpp, thực hiện việc liên kết nó với lớp Money vừa tạo thông qua lệnh: #include “Money.h” và tiến hành biên dịch lại chương trình.
Ngay sau khi biên dịch chương trình xong, VC++ báo một lỗi assertion. Nhấn phím F4 chúng ta sẽ nhảy đến nơi kiểm tra loại tiền tệ của đối tượng Money vừa tạo. Lỗi này có ý nghĩa là chuỗi ký thự đó không phải là một giá trị được mong đợi. Điều này chỉ xảy ra do hai nguyên do: biến thành viên không được khởi tạo một cách đúng đắn hoặc hàm trả về một giá trị sai. Sau khi kiểm tra lại chúng ta phát hiện điều này xảy ra do biến không được khởi tạo đúng. Đoạn chương trình được sửa lại như sau:
Money.h
Money( double amount, std::string currency ) : m_amount( amount )
, m_currency( currency ) { {
}
Tiến hành biên dịch lại chương trình và không có lỗi nào xảy ra nữa.
Tạo thêm các bài kiểm tra khác
1. Kiểm tra bằng
Một vấn đề đặt ra là kiểm tra xem 2 đối tượng Money có bằng nhau hay không. Chúng ta hãy bắt đầu bằng việc thêm vào 1 bài kiểm tra mới vào dự án hiện tại và sau đó thêm vào các phương thức của riêng chúng ta. MoneyTest.h
CPPUNIT_TEST_SUITE( MoneyTest ); CPPUNIT_TEST( testConstructor );
Lê Hùng – Vũ Thế Hiển - Nguyễn Đình Hiển –Phạm Đào Minh Vũ – Trương Quang Bình Long Trang 36
CPPUNIT_TEST( testEqual ); CPPUNIT_TEST_SUITE_END(); public: ... void testEqual(); MoneyTest.cpp void MoneyTest::testEqual() { // Set up
const Money money123FF( 123, "FF" ); const Money money123USD( 123, "USD" ); const Money money12FF( 12, "FF" ); const Money money12USD( 12, "USD" ); // Process & Check
CPPUNIT_ASSERT( money123FF == money123FF ); // ==
CPPUNIT_ASSERT( money12FF != money123FF ); // != amount
CPPUNIT_ASSERT( money123USD != money123FF ); // != currency
CPPUNIT_ASSERT( money12USD != money123FF ); // != currency and != amount
}
Tiếp theo chúng ta thực hiện viết chương trình cho toán tử == và toán tử != của lớp Money. Money.h class Money { public: ...
bool operator ==( const Money &other ) const {
return m_amount == other.m_amount && m_currency == other.m_currency; }
bool operator !=( const Money &other ) const {
return (*this == other); }
};
Thực hiện việc biên dịch chương trình và chúng ta phát hiện một lỗi. Nhấn phím F4 để xem chương trình bị lỗi gì và chúng ta phát hiện rằng toán tử != có “vấn đề”. Đoạn chương trình sau sẽ “giải quyết” vấn đề này.
bool operator !=( const Money &other ) const {
return !(*this == other); }
Biên dịch lại chương trình và không có lỗi nào được phát hiện nữa.
2. Cộng tiền tệ
Thêm một phương thức testAdd vào lớp MoneyTest để tiến hành kiểm tra thao tác cộng 2 tiền tệ. MoneyTest.cpp void MoneyTest::testAdd() { // Set up
const Money money12FF( 12, "FF" ); const Money expectedMoney( 135, "FF" ); // Process
Money money( 123, "FF" ); money += money12FF; // Check
CPPUNIT_ASSERT_EQUAL( expectedMoney.getAmount, money.getAmount() ); // += works
CPPUNIT_ASSERT( &money == &(money += money12FF) ); // += returns ref. on 'this'.
}
Trong khi viết chương trình, chúng ta tự hỏi là việc cộng 2 loại tiền tệ khác nhau sẽ dẫn đến kết quả gì? Dễ thấy rằng điều đó sẽ gây ra một lỗi và lỗi này phải được báo cho người sử dụng biết, có thể là quăng ra một exception là IncompatibleMoneyError, khi cộng 2 loại tiền khác nhau. Chúng ta sẽ viết một bài test khác cho vấn đề này. Bây giờ chúng ta hãy thêm một số lệnh để phương thức testAdd hoạt động. Money.h class Money { public: ...
Money &operator +=( const Money &other ) {
m_amount += other.m_amount; return *this;
}}; };
Biên dịch chương trình, mọi chuyện diễn ra tốt đẹp. Bây giờ để kiểm tra lại rằng các bài kiểm tra của chúng ta hoạt động đúng, ở đoạn chương trình ở trên, đổi m_amount += thành -=. Tiến hành biên dịch lại chương trình và kiểm tra rằng có một lỗi xảy ra. Thay đổi lại -= thành += để mọi bài kiểm tra đều được vượt qua.
Lê Hùng – Vũ Thế Hiển - Nguyễn Đình Hiển –Phạm Đào Minh Vũ – Trương Quang Bình Long Trang 38
Bây giờ chúng ta tiến hành viết chương trình kiểm tra 2 loại tiền tệ có giống nhau hay không trước khi tiến hành việc cộng chúng. Bài kiểm tra này sẽ quăng ra một biệt lệ (exception) IncompatibleMoneyError. Thu viện CppUnit có thể giúp chúng ta thực hiện việc này.
MoneyTest.h
class MoneyTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE( MoneyTest ); CPPUNIT_TEST( testConstructor ); CPPUNIT_TEST( testEqual ); CPPUNIT_TEST( testAdd );
CPPUNIT_TEST_EXCEPTION( testAddThrow, IncompatibleMoneyError ); CPPUNIT_TEST_SUITE_END();
public: ...
void testAddThrow(); };
Với cách quy ước mặc nhiên, những bài kiểm tra nào tận cùng bằng “Throw”, sẽ ngầm định rằng bài kiểm tra đó sẽ quăng ra một biệt lệ (exception).
MoneyTest.cpp
void MoneyTest::testAddThrow() {
// Set up
const Money money123FF( 123, "FF" ); // Process
Money money( 123, "USD" );
money += money123FF; // should throw an exception
}
Money.h
#include <string> #include <stdexcept>
class IncompatibleMoneyError : public std::runtime_error {
public:
IncompatibleMoneyError() : runtime_error( "Incompatible moneys" ) {
}}; };
Tiến hành biên dịch lại chương trình và như mong đợi, hàm testAddThrow() bị một lỗi exception. Lỗi này được sửa lại như sau:
Money.h
Money &operator +=( const Money &other ) { if ( m_currency != other.m_currency ) throw IncompatibleMoneyError(); m_amount += other.m_amount; return *this; }
Biên dịch lại chương trình và mọi chuyện diễn ra tốt đẹp.
---Hết ---
Lê Hùng – Vũ Thế Hiển - Nguyễn Đình Hiển –Phạm Đào Minh Vũ – Trương Quang Bình Long Trang 40