注: 長いです。
スクリプト言語でのxUnit実装を使ったことがある方なら、テストを定義するだけでテストが実行されることが当たり前ではないでしょうか。c2.comのWikiによると、これはTest Collectorというそうです。定義したテストを自動的に集めてくる機能のことです。
一般的にTest Collectorの機能は言語が提供するリフレクション機能やメタプログラミング機能を使って実現されます。
例えば、Rubyのtest-unit 2.xでは、リフレクションを使う方法とメタプログラミングを使う方法の両方をサポートしています。リフレクションを使う方法ではObjectSpace.each_object(Class)
ですべてのクラスを取得し、その中のTest::Unit::TestCase
のサブクラスを集めます。メタプログラミングを使う方法ではTest::Unit::TestCase.inherited
を定義して、サブクラスが定義された時のフックでそのサブクラスを集めます。
Pythonでもモジュールオブジェクトからモジュール内のオブジェクトにアクセスすることができるので、同様の方法でテストを集めることができます。JavaScriptでも、オブジェクトに定義されているプロパティを列挙することができるので、同様の方法でテストを集めることができます。(JavaScriptとXULで実装されているUxUも同様のことをしています。)
一方、CやC++ではリフレクション機能やクラスをファーストクラスオブジェクトとして扱う機能がないため、自動でテストを集めるためには一工夫必要になります。一昔前のxUnitでは、定義したテストを手動で登録していました。
それでは、C/C++での一工夫の方法として以下の4つをxUnit実装と一緒に紹介します。C++用のxUnitを選択する時の参考にしてください。
最初はCppUnitのケースです。CppUnitではテストを定義するだけでは、自動でテストを集めてはくれません。しかし、便利マクロを用意して、手動でテストを登録する面倒さを減らしています。
以下はCppUnit Cookbookにあるソースコードをベースにしています。public内のテスト定義とは別にCPPUNIT_TEST_SUITE
からCPPUNIT_TEST_SUITE_END
の間でテストを登録しています。
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 31 32 33 34 35 36 37 38 39 |
// complex-number-test.cpp #include <cppunit/extensions/HelperMacros.h> class ComplexNumberTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( ComplexNumberTest ); CPPUNIT_TEST( testEquality ); CPPUNIT_TEST( testAddition ); CPPUNIT_TEST_SUITE_END(); private: Complex *m_10_1, *m_1_1, *m_11_2; public: void setUp() { m_10_1 = new Complex( 10, 1 ); m_1_1 = new Complex( 1, 1 ); m_11_2 = new Complex( 11, 2 ); } void tearDown() { delete m_10_1; delete m_1_1; delete m_11_2; } void testEquality() { CPPUNIT_ASSERT( *m_10_1 == *m_10_1 ); CPPUNIT_ASSERT( !(*m_10_1 == *m_11_2) ); } void testAddition() { CPPUNIT_ASSERT( *m_10_1 + *m_1_1 == *m_11_2 ); } }; CPPUNIT_TEST_SUITE_REGISTRATION( ComplexNumberTest ); |
実行する場合は以下のようなmain
関数を定義する必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// main.cpp #include <cppunit/extensions/TestFactoryRegistry.h> #include <cppunit/ui/text/TestRunner.h> int main( int argc, char **argv) { CppUnit::TextUi::TestRunner runner; CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry(); runner.addTest( registry.makeTest() ); bool wasSuccessful = runner.run( "", false ); return wasSuccessful; } |
上記の二つのファイル(とComplexNumberの実装)を使ってビルドします。
% g++ -o complex-number-test complex-number-test.cpp main.cpp \ -lcomplex-number -lcppunit
テストを実行するにはビルドしたバイナリを実行します。
% ./complex-number-test .. OK (2 tests)
マクロを使ってテスト登録を簡単にしている(自動化まではしていない)例としてCppUnitを紹介しました。
CPPUNIT_TEST_SUITE
などの便利マクロを使わない場合は定義したテスト名(上の例ではtestEquality
とtestAddition
)以外のことも気にしなければいけなくなります。便利マクロを使うと、テスト名だけわかっていればよいので、それに比べるとだいぶテスト作成が楽になっています。
しかし、テストを定義だけして登録し忘れたということを回避することができません。また、テストケース定義とは別にmain
関数も定義する必要があり、テスト以外のことにも気を配る必要があることにも注意が必要です。
C++で書かれたテストコードを直接C++コンパイラでコンパイルするのではなく、テストコードに必要なコードを追加したC++ソースコードを生成して、それをコンパイルする方法です。C++コンパイラでのビルドする前に一度変換処理を行えるので、テストコードへの記述が減ることが利点ですが、変換処理を行うのがやや面倒です。自動化されれば気にならなくなるでしょう。
まずはCxxTestのケースです。CxxTestではソースコードを直接ビルドするのではなく、C++のソースコードからテスト登録処理などを付加したC++ソースコードを生成し、それをビルドします。
以下はCxxTest User Guideにあるソースコードをベースにしています。テストの定義だけでテスト登録処理は含まれていません。
1 2 3 4 5 6 7 8 9 10 11 12 |
// MyTestSuite.h #include <cxxtest/TestSuite.h> class MyTestSuite : public CxxTest::TestSuite { public: void testAddition( void ) { TS_ASSERT( 1 + 1 > 1 ); TS_ASSERT_EQUALS( 1 + 1, 2 ); } }; |
以下のようにビルドします。
% cxxtestgen --error-printer -o cxxunit-tests.cpp MyTestSuite.h % g++ -o cxxunit-tests cxxunit-tests.cpp
cxxtestgen
でMyTestSuite.h
にあるテスト定義にテスト登録処理などを加えてcxxunit-tests.cpp
を生成します。余談ですが、cxxtestgen
はPythonスクリプトです。また、CxxUnitはライブラリを提供せず、ヘッダーファイルのみを提供します。
バイナリを実行するとテストが走ります。
% ./cxxunit-tests Running 1 test.OK!
テスト登録が完全に自動化されているのでCppUnitよりも新規テストの追加が容易です。テストの登録しわすれもありません。ただ、cxxtestgen
とC++コンパイラで2回コンパイルする必要があることが少し手間だと言えます。
続いてQtが提供するQTestLibのケースです。QTestではQtが提供するスロットの仕組みを使って、定義されているテストを集めます。スロットがどのように定義されているかをプログラム中から扱うために、QtはC++のソースコードをプリコンパイルしますが、QTestでも同様にプリコンパイルする必要があります*1。
以下はQTestLibのチュートリアルにあるソースコードををベースにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// test-qstring.cpp #include <QtTest/QTest> class TestQString: public QObject { Q_OBJECT private slots: void toUpper() { QString str = "Hello"; QCOMPARE(str.toUpper(), QString("HELLO")); } }; QTEST_MAIN(TestQString) #include "test-qstring.moc" |
QTestLibでもmain
関数を定義しなければいけませんが、QTEST_MAIN
という便利マクロが用意されています。
以下のようにビルドします。
% mkdir test-qstring % mv test-qstring.cpp test-qstring % cd test-qstring % qmake -project "QT += testlib" % qmake % make
バイナリを実行するとテストが走ります。
% ./test-qstring ********* Start testing of TestQString ********* Config: Using QTest library 4.5.3, Qt 4.5.3 PASS : TestQString::initTestCase() PASS : TestQString::toUpper() PASS : TestQString::cleanupTestCase() Totals: 3 passed, 0 failed, 0 skipped ********* Finished testing of TestQString *********
このようにQTestLibではテスト登録のために必要なコードはQTEST_MAIN
でクラスを指定している部分だけです。個々のテストは指定する必要がありません。
メタオブジェクト情報を生成すること、また、それを読み込んでいる#include "test-qstring.moc"
のところはQTestLib独自のことではなく、Qt全般のことです。そのため、Qtを利用している場合は追加で必要な作業とはいえないでしょう。つまり、QTestLibのテストを集める方法は完全には自動化されていませんが、Qt開発者にはそれほど負担もかからず自然に書けるようになっている使いやすいAPIといえます。一方、Qt開発者でない場合は、面倒に見えるでしょう。
CppUnitでもマクロでテストを登録していますが、それをもう一歩進めたのがこの方法です。CppUnitでは、テスト定義は通常の関数定義でしたが、この方法ではそこでマクロを使い、テスト定義と同時にテストを登録します。
まずは、Google Testです。Google Testではテスト定義時にTEST
マクロを使います。以下はGoogleTestSamplesにあるソースコードをベースにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// test-factorial.cpp #include <gtest/gtest.h> int Factorial(int n) { int result = 1; for (int i = 1; i <= n; i++) { result *= i; } return result; } TEST(FactorialTest, Negative) { EXPECT_EQ(1, Factorial(-5)); EXPECT_EQ(1, Factorial(-1)); EXPECT_TRUE(Factorial(-10) > 0); } int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } |
プリコンパイル方式でもテストの登録忘れはありませんが、この方法でも登録を忘れることがありません。テスト定義の方法が通常の関数定義とは異なる書式になることに慣れることができるのであれば、この方式で負担が少なくテストを書けるようになるでしょう。
以下のようにビルドします。
% g++ -o test-factorial test-factorial.cpp -lgtest
バイナリを実行するとテストが走ります。
% ./test-factorial [==========] Running 1 test from 1 test case. [----------] Global test environment set-up. [----------] 1 test from FactorialTest [ RUN ] FactorialTest.1 [ OK ] FactorialTest.1 (0 ms) [----------] 1 test from FactorialTest (0 ms total) [----------] Global test environment tear-down [==========] 1 test from 1 test case ran. (0 ms total) [ PASSED ] 1 test.
上記の例では触れていませんが、フィクスチャ(setup/teardown)を使う場合は、テストクラス名を揃える必要があるなど、同じグループのテストを作る場合は重複する部分がでてしまいます。例えば、QTestLibのようにクラス内にテストを定義する方法では以下のようになります。
1 2 3 4 5 6 7 8 9 |
class MyTest { void setup() {...} void teardown() {...} void test1() {...} void test2() {...} void test3() {...} } |
一方、Google Testの場合は、スコープが使えず、以下のようにクラス名を複数回書く必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class FooTest : public testing::Test { protected: virtual void SetUp() { b_.AddElement(3); } Foo a_; Foo b_; }; TEST_F(FooTest, InitializesCorrectly) { EXPECT_TRUE(a_.StatusIsOK()); } TEST_F(FooTest, ReturnsElementCountCorrectly) { EXPECT_EQ(0, a_.size()); EXPECT_EQ(1, b_.size()); } |
マクロを使っている場合は、間違ったテストクラス名を指定するなどコンパイルエラーになったときに意味の分からないエラーメッセージを目にすることがあるというのも注意しなければいけないポイントです。エラーメッセージを使えないと問題を発見することが難しくなります。
次に、Boost Test Libraryです。やり方はGoogle Testとだいたい同じで、Boost Test LibraryではBOOST_AUTO_TEST_CASE
を使います。
1 2 3 4 5 6 7 8 9 10 11 |
// test-add.cpp #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE AddTest #include <boost/test/unit_test.hpp> int add( int i, int j ) { return i+j; } BOOST_AUTO_TEST_CASE( add_test ) { BOOST_CHECK_EQUAL( add( 2,3 ), 5); } |
最初にBOOST_TEST_DYN_LINK
とBOOST_TEST_MODULE
を定義しておくと、Boost Test Libraryではmain
関数を定義する必要はありません。
以下のようにビルドします。
% g++ -o test-add test-add.cpp -lboost_unit_test_framework
バイナリを実行するとテストが走ります。
% ./test-add Running 1 test case... *** No errors detected
Google Testと同じくマクロが気にならない場合やBoostに慣れている場合はテストが書きやすいでしょう。
マクロを利用する方法は言語の構文を工夫してテストを集めています。プリコンパイル方式では言語の構文はそのままで、コンパイル前に付加情報を加えることでテストを集めています。
一方、最後の共有ライブラリから探す方法ではコンパイル後の共有ライブラリから情報を取得してテストを集めます。この方式では、テストを共有ライブラリとして作成し、テスト実行用のコマンドからその共有ライブラリを読み込み、テストを実行します。こうすることにより、テスト側にテスト登録処理を埋め込む必要がなくなります*2。共有ライブラリの中からテストを見つける処理はテスト実行コマンドが頑張るからです。
最初はWinUnitです。やり方は共有ライブラリからテストを集める方式なのですが、書き方はマクロを使う方式です。テストを定義するときはBEGIN_TEST
とEND_TEST
で囲みます。
1 2 3 4 5 6 7 |
#include "WinUnit.h" BEGIN_TEST(AddTest) { WIN_ASSERT_TRUE(3 == add(1, 2)); } END_TEST |
すでにGoogle TestやBoost Test Libraryで見たように、この使い方であれば、共有ライブラリにする必要はありません。マクロの中で一工夫することでテストの自動登録を実現できるからです。
WinUnitの利点はVisual C++で使いやすいことでしょう。マクロを使ったAPIが気にならないVisual C++開発者には有力な選択肢です。
最後はCutterです。CutterはC言語用の単体テストフレームワークとして開発されていましたが、先日リリースされた1.1.0で大きくC++対応を強化しています。
CutterではWinUnitとは違いマクロを利用しません。通常通り関数を定義するとテストとして認識されます。ただし、すべての関数がテストとして認識されるのではなく、test_
からはじまる名前の関数だけをテストとして認識します。
1 2 3 4 5 6 7 8 9 |
#include <cppcutter.h> namespace calc { void test_add() { cppcut_assert_equal(5, add(2, 3)); } } |
マクロを利用してテストを自動登録する方式では、フィクスチャ定義時に名前を揃える必要がありましたが、Cutterでは以下のようにnamespace内にsetup()
/teardown()
を定義するだけです。namespaceでグループ化されたテスト全体でフィクスチャを共有します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <cppcutter.h> namespace calc { void setup() {...} void teardown() {...} void test_add() // calc::setup()/calc::teardown()が呼び出される { cppcut_assert_equal(5, add(2, 3)); } void test_sub() // calc::setup()/calc::teardown()が呼び出される { cppcut_assert_equal(5, add(8, 3)); } } |
この方式では通常のC++プログラムと同様にテストを書くことができるため、新しくテストを書くことの敷居が低くなります。しかし、tes_
などタイプミスをしてしまった場合に、どうしてテストが実行されないのかに気づきにくいという問題点があります。
テストも通常のプログラムと同様に開発したい場合はマクロを使わないこの方式がオススメです。
C++用の各種xUnitでのテストの書き方を、方式毎に分類して紹介しました。どんなバックグラウンドを持っているかにより、選びやすいxUnitは変わるでしょう。Visual C++開発者であればWinUnitを選ぶことが多いでしょうし、Qt開発者であればQtTestLibを選ぶことが多いでしょう。しかし、バックグラウンドから選ぶだけではなく、テストの書きやすさも判断材料に加えてみてはいかがでしょうか。
継続して開発すればそれに伴ってテストも増えていきます。しかし、テストは面倒くさがって飛ばしてしまいがちです。新しくテストを書く敷居が下がれば、テストを面倒くさがることが少なくなり、安心して開発を続けていくための土台を固めることができます。新しくテストを書く敷居を下げることは開発を継続するのであれば割に合うということです。
今回は「新しいテストの書きやすさ」を軸に様々なxUnitのやり方を紹介しました。C++用xUnitを選択する時の参考にしてみてください。
念のため書きますが、オススメはCutterです。
こんにちは。下田(Piro)です。
昨日2009年11月8日に開催されたFirefox Developers Conference 2009にて、トークセッション「Aza Raskin に一問一答!」にパネリストとして参加しました。また、懇親会でのライトニングトーク第2部にて発表を行いました。参加された皆様、お疲れ様でした。また、セッションにお越しいただいた皆様、誠にありがとうございます。
発表資料および映像は以下よりご覧いただけます。
また、ライトニングトーク中で紹介しているアドオン「システムモニター」の最新版であるVer.0.3は、以下からダウンロードできます。
以下、イベントの感想と、イベント中に語ることができなかった点について書いていきたいと思います。
このセッションでは、次期Firefoxでの標準搭載も視野に入れて開発が進められているJetpackや、新しいUIの可能性を模索するUbiquityの開発者として知られるAza Raskinさんに対して、現在Firefoxアドオンを開発している・開発した経験がある人の立場からの質問を私が、主にWebアプリケーションの開発を行っておりこれからJetpack用のスクリプト(Jetpack feature)の開発に携わる可能性がある人の立場からの質問を天野さんが行う形で、Firefoxの今後とWebアプリケーションの将来像について様々な話を聞かせていただきました。
Firefoxはアドオン(拡張機能)によるカスタマイズ性の高さが最大の特長ですが、自由度の高さゆえに、アドオンの開発には様々な準備と知識が必要になるという欠点もあります。Jetpackは、この欠点をカバーしてFirefoxの機能を拡張するスクリプトをより容易に配布・利用できるようにする物として開発されている、新しいアドオンのメカニズムです。「拡張機能」がテーマである今回のFirefox Developers Conference 2009においては、避けて通れない話題ですね。
今回のトークセッションにあたって事前にいくつかのJetpack featureを開発したのですが、その際に最も強く感じた事は、APIについての不満でした。現状ではAPIに関するドキュメントが圧倒的に不足しており、また、APIがドラスティックに変更されている最中であるため、安定したJetpack featureの開発および利用はまだまだ難しいのが実情です。セッション中でも質問を行いましたが、これについては、むしろ今が開発に口出ししてAPIをより良い物にしていくチャンスと捉えてほしいという回答をいただきました。とはいえ、APIドキュメントの重要性は彼らの間でも認識されており、そのための体制を整えているところであるとの話も聞けました。
Azaさんは、セカンドシステム症候群に陥ってはならないという事を再三述べていました。これまでのアドオンの仕組みに多くの不満があるからといって、その代替として新たに登場してきたJetpackに過剰な要求をして完璧な物を最初から求めると、議論が紛糾するばかりで実装が停滞し、Jetpackという仕組み自体がいつまで経っても完成しなくなってしまいます。ほどほどの所でまずは皆に使ってもらい、その上で実際の利用状況を見ながら少しずつ不足箇所を補っていく、という姿勢が重要ですね。
Jetpack featureで利用可能なライブラリとしては、現在はjQueryが標準添付されていますが、ゆくゆくはPerlにおけるCPANのように、様々なライブラリを簡単に利用できるようにする計画もあるそうです。また、現状のJetpackも将来のバージョンも、jQueryを使うことは必須というわけではなく、ライブラリの機能を使わずにJetpack featureを開発しても問題は無いとのことです。なお、私も天野さんも既存のライブラリをほとんど利用していない理由について、Azaさんより逆に質問をされるという場面もありました。(天野さんの場合は主に既存のライブラリのオーバーヘッドが気になるためで、私の場合はFirefox用アドオンの開発のみを行う都合上、ライブラリの最大のメリットである「ブラウザ間の差異の吸収」の恩恵を受けにくいというのが理由です。)
天野さんがWebアプリの開発者の観点から投げかけられた質問として、WebのUIを良くするにはどのようにすればよいか?という物もありました。これについてAzaさんは、作り手側が絶対に手出し・口出ししないようにして、目の前でエンドユーザに実際に使ってもらいその様子を観察すれば、WebのUIはもっと良くなるだろうとおっしゃっていました。ユーザビリティ・テストはUI開発の基本と言えますが、DTPなど視覚的デザインの文脈で捉えられることがまだまだ多いWebの世界においても、きちんと「インターフェース」としての作り方を意識する必要があるということですね。
国ごとの文化の違いがUIに与える影響について、Azaさんは欧米と中国のWebブラウズの仕方の違いを例に挙げてお答え下さいました。曰く、欧米や日本では1つの画面にかじりついて操作するのが一般的であるのに対し、中国では画面から少し離れて、画面内に非常に多くの機能・要素を詰め込んでそれらを平行して利用する場合が多いそうです(そのため、Googleのかつてのシンプルなトップページは不評だったそうです)。そういった文化ごとの利用形態の違いに合わせるために、末端にいる人達にUIのデザインを行う権限を持たせる必要があるのではないか、という意見も示されていました。
他のブラウザの隆盛、特にWebKitが多数のプロジェクトで採用されている事についての質問もありました。これについては、かつては止まったWebブラウザの進化をFirefoxが刺激して活性化させたように、今はWebKitがWebを活性化させているとして、その結果Webがより便利になるのであれば最終的な勝者は我々エンドユーザだ、との考えをお答えいただきました。
というように、Jetpackの話題のみにとどまらず、WebのUI一般の話にまで言及したトークセッションとなりましたが、皆様お楽しみいただけましたら幸いです。
ライトニングトークへの参加希望者が多かったため、過去に発表経験のある数人については懇親会の場で発表を行うこととなりました。今回はシステムモニターで行った、アドオンによるWebアプリケーション向けAPIの提供方法について発表しました。
「scriptable hardware」というキーワードで、基調講演でChris BlizzardさんがFirefoxの加速度センサー対応やカメラ用APIの実験について語っていらっしゃいました。クリアコードでも独自に同様の研究を行っており、システムモニター以外にも、指紋認証アドオン「Fingerprint-Auth」の実装を進めております。また、その開発の過程で浮上してきたアイデアとして、USB機器全般をJavaScriptから制御できるようにしてみてはどうかという話もあり、それについても「進行中のプロジェクト」としてお話しさせていただきました。Fingerprint-Authについては実際にお試しいただける形の物を近日中に公開する予定ですので、どうぞお楽しみに。
セッション「js-ctypes ~ネイティブコードを呼び出す新しいカタチ」では、JavaScriptからプラットフォームネイティブなバイナリの機能を呼び出すより平易な方法を提供するFirefox 3.6からの新機能js-ctypesを紹介されていましたが、システムモニターやFingerprint-AuthのようにJavaScriptのグローバルな名前空間にAPIを提供しようと思うと、現状ではXPCOMコンポーネントとして実装を行う必要があります。また、XPCOMコンポーネントはC++での開発となるため、各プラットフォーム向けのビルドやnsISecurityCheckedComponentインターフェースの実装などの作業が必要となります。残念ですね。
なお、発表ではすべての実装がJavaScriptによって行われているXUL/MigemoでのAPIの提供方法を例として紹介しました。JavaScript製XPCOMコンポーネントの場合は、比較的簡単に機能をWebアプリケーション向けのAPIとして公開することができます。作成手順についてはFirefox 3 Hacks等の解説と発表資料中の説明を併せてご覧下さい。
株式会社はてなさんのはてなブックマークFirefox拡張についての発表では、開発に使用したツールとして弊社開発のテスティングフレームワークUxUをご紹介いただけました。主にデータベース関連の機能等のユニットテストに利用されているとのことで、非同期処理が絡むテストの開発に役立ったとのお言葉をいただけたのは嬉しかったです。また、私が個人的に開発している各種のアドオンについても、ソースコードをアドオン開発の参考にしていただけたそうで、ありがたい限りです
なお、UxUでは最近のバージョンアップでより使いやすいユーザ操作エミュレーション用のAPIが追加されました。基本部分のユニットテスト以外にも、GUIが関係する機能テストやインテグレーションテストにもUxUを活用していただけたらと思っております。
UbiquityにもJetpackにも共通している1つの狙いとして、「より多くの人が開発を行えるようにする」という目標があるそうです。より簡単に開発できるようになり、より多くの人が開発できるようになれば、より多くのイノベーションが生まれる、というのは前回のFirefox Developers Conferenceの際にもAzaさんが語られていた話ですが、AutoPagerize、ひいてはその原点であるGoogleAutoPagerが、どちらもGreasemonkeyスクリプトという世界から登場したことは、まさにその象徴的な出来事だと思います。
これはFirefoxのアドオン開発のみに限られた話ではなく、Chris Blizzardさんが語ったキーワード「scriptable hardware」もそれに連なる話であると言えるでしょう。折しも、先日GoogleがClosure Toolsという、JavaScriptでのアプリケーション開発のためのツール集を公開しました。APIやツールなど様々な側面から、Webクライアント上で動作する高機能なアプリケーションを開発しやすくするための土壌が整いつつあります。Webアプリケーションがエンドユーザからただの「アプリケーション」として扱われるようになる、Web OSという未来が本当にすぐそこまで来ているのだということを、改めて意識させられたイベントでした。
今月末、FSIJ月例会でテスティングフレームワークについて話します。月例会の概要は以下の通りです。都合があう方はぜひお越しください。
(tokyo-emacs #x02)で話したときにお会いした上野さんに声をかけてもらいました。声をかけていただきありがとうございます。
事前に打ち合わせなどはないようなので、自由な形式でやる予定です。
2時間ありますが、ずっと話し続けるわけではありません*1。こちらから考えていることや技術的なことなどを紹介し、それを話題としてディスカッションを挟みながら進めていきます。テスティングフレームワークやテストについて思っていることがある方はぜひ参加してその考えを聞かせてください。
以下の3部構成にする予定です。ここでいう「テスト」とは実装をする開発者自身が書く「自動化されたテスト」のことです。
今では、「テストは書いた方がよい」というのはみんなわかっていることです。しかし、「テストのないコードは怖くてさわれない」という感覚はそうではありません。それがテストが当たり前の人とそうでない人の差です*2。では、どうすればテストが当たり前になるのか。まずは、それについて話し、ディスカッションします。
次に、テストが当たり前の人が価値のあるテストを継続して書くために、テスティングフレームワークが提供するべきものはなにかを考えます。
最後に、現在のテスティングフレームワークはどうなっているかを扱います。先日、C++用xUnitでのテストの書き方を紹介しましたが、他の言語用のテスティングフレームワークでの書き方や、もしかしたら、どのような実装で実現しているかまで紹介できるかもしれません。
随時、参加者からの意見を受け入れますが、それぞれの話題毎および最後にもまとまったディスカッションの時間をとる予定です。
今月のFSIJ月例会でテスティングフレームワークについて話すことになったので、それの告知をしました。参加費は無料なので興味のある方はお気軽に参加してみてください。
先日開催されたFSIJ月例会でテストとテスティングフレームワークについて話しました。声をかけてくれた上野さん、ありがとうございます。
これまでの経験から感じていることをまとめたものになっています。どうにかしたいけど、まだよいアイディアがなくて悩んでいる、といったものも含まれています。例えば、違いをわかりやすく示すことはいろいろ工夫できるけど、なかったことをわかりやすく示すことは難しいといったことです。
最後まで話しつづけるのではなく、随時ディスカッションをはさむ形で進みました。参加者のみなさんからもたくさんの意見がでてとても有意義でした。
GUIやDTP、ネットワーク・ハードウェア周辺などテストを自動化することが難しい領域のテストはみなさん悩んでいるところでした。今回の会で決定的な解決策がでたわけではないのですが、悩んでいる部分、他の人が持っているよいアイディアを共有できたことは成果と言えます。明日から劇的に変わるというものではありませんが、確実によくなっていけるというものです。
話の中に何度かでていますが、「完璧を求めない」ことが重要です。完璧を求めてテストがストレスになってしまうことよりも、自分たちのペースでよい状態を継続し、よいソフトウェアの開発を続けられるようにすることの方が重要です。このあたりの力の入れ具合、テストが目的ではなくよいソフトウェアを開発することが目的であることを忘れないことで「壁」を越えることができるでしょう。
来月中旬の12/14(月)に〜Ruby on Rails Technical Night〜Ruby on RailsセミナーでActive Directoryと連携したRailsアプリケーションの開発方法について話します。セミナーの概要は以下の通りです。都合があう方はぜひお越しください。
さも1人で話すように書いていますが、そんなことはなく、株式会社ローハイド.の吉見さんと株式会社万葉の河野さんの3人で、3部構成です。運用のお話や開発時のお話をされるようなので、そちらに興味のある方も参加してみてください。
内容はタイトルの通りで、RailsアプリケーションからActive Directoryの情報を利用する方法、注意しなければいけない点などについて話します。社内システムなど、すでにActive Directoryを導入している環境で動作するRailsアプリケーションを開発する場合、独自にアカウントを管理するのではなく、Active Directory上のアカウント情報を利用する方が、利用者の使い勝手もよくなりますし、運用者の負担も減ります。そういった場合にどのようにActive Directory上のアカウント情報を利用するのがよいか、ということをコード例も示しながら説明します。
Active Directoryとの接続には、ActiveLdap(参考: Rubyist Magazine - ActiveLdap を使ってみよう(前編))を使います。つまり、Active DirectoryをLDAPサーバとして使った場合のRailsアプリケーションの作り方とも言えます。よって、この話の内容はOpenLDAPなどActive Directory以外のLDAPサーバにも応用できます。LDAPサーバと連携したRailsアプリケーションに興味がある方にも楽しんでもらえるのではないでしょうか。
来月のRailsセミナーでRailsとActive Directoryについて話すことになったので、それの告知をしました。参加費は無料なので興味のある方はお気軽に参加してみてください。現時点で定員の半分ほど埋まっているようなので、気になる方はお早めにどうぞ。