Antoine.st 2005-01

2005-01-31

Off-recording

オフレコって言い方しますけど、「Off recoding」なんでしょうか。ま、どっちにしろ書けない話ってことですね。

個人のサイトなんで、あんまり気にせずに書くことにしてます。とはいえ、やっぱり書けないことはあるわけで。「書けないこと」というよりは、「わざわざ書かないこと」でしょうか。会社のことなんて書けないものですし、書いても内輪ウケになりやすいので、あんまり面白くなかろうと。

かといって、プライベートなことも大して面白い話があるわけでもなし。精神的に追い詰められると、なぜかタイピングが進むわけですが、そんなドロドロした頭の中身を書きなぐっても、たぶん、読んだ人をイヤーな気持ちにさせるだけでしょうし。

というわけで、中途半端に技術的な話に落ち着いてしまうわけです。


2005-01-28

Becky! Intenet Mail 2.20 beta

Becky のマイナーバージョンアップグレードのベータ版が公開されました。もう beta 5 になります。さすがに最初から試すのは怖いので、beta 4 になってからお試し。

特に問題もなくいい感じで動いてます。


2005-01-24

Give up

すいません。ダメでした。Passport 認証をなんとかかんとかやろうとしてたんですが、どうにもこうにもうまく行きません。Passport SDK をダウンロードして、ざっと見てみたんですが、どうやってサーバー側を作るのか、って話ばかりで、クライアントの実装方法がわからず。横取り丸 も HTTPS には対応してなくて、何をやってるのかわかりません。

それなりに何とかなったような気がしたんですが、

  1. 認証が必要なサイトに Request
  2. Cookie を食べてから、Passport のログインサイトに Post
  3. ユーザー名、パスワードをログインサイトに Post
  4. 2. に戻る...。

という感じで無限ループに陥ってしまいました。たぶん、3 番目の Post 方法が何か間違ってるんだろうなぁ...。


2005-01-23

HttpWebRequest for HTTPS

HTTPS のサイトに対して、HttpWebRequest で結果を取得する、ってのをやっていたんですが、どうもうまく行きません。何度試しても、Time Out で返ってきてしまいます。

サンプルを見る限り、何か特殊な処理が必要ってわけでもないようなんだけど...。

うーん。今日試したらうまく行った...。何なんでしょ?


2005-01-20

Parsing by Regular expression

正規表現で HTML をパースするプログラムを作ってたんですが、</TD> 閉じタグがなくても、きちんと Internet Explorer は表示してくれるんですね。たぶん、見えないところでいろいろやってくれているのでしょう。

自前でやろうとすると、タグがひとつなくなっただけでえらい大変です。


2005-01-18

Excel Macro

お手軽マクロ。#Div/0 エラーを消すための式を入れる、というだけ。まじめにやるんなら、いろいろ方法はあるんでしょうけど、ついつい楽な方向に逃げちゃいますね。いかんいかん。


  Sub ReplaceError2Check()
      
    Dim i As Integer
    Dim j As Integer
    Dim buf As String
    Dim arg1 As String
    Dim arg2 As String
    Dim res As VbMsgBoxResult
  
    Const MSG = "Do you want to fix it?"
    
    With Range("A1")
      For i = 0 To 100
        For j = 0 To 100
          buf = .Offset(i, j).Formula
          If InStr(buf, "/") > 0 Then
            arg1 = Mid(Split(buf, "/")(0), 2)
            arg2 = Split(buf, "/")(1)
            res = MsgBox(buf & vbNewLine & MSG, _
                         vbYesNo Or vbQuestion)
            If res = vbYes Then
              .Offset(i, j).Formula = _
                Replace(Replace("=IF(%2=0,0,%1/%2)", _
                                "%1", arg1), _
                        "%2", arg2)
            End If
          End If
        Next j
      Next i
    End With

  End Sub


2005-01-17

HDD

自宅用の外付け HDD のディスクが死んでました...。RAID でよかった。


2005-01-16

General Network Error

SQL Server で、えらい時間のかかるクエリーを実行していたところ、「[Microsoft][ODBC SQL Server Driver][DBNETLIB]ConnectionRead (WrapperRead()).」というエラーが発生しました。Windows 2000 Server 環境なんですが、どうも これ っぽいです。

ということで、クエリアナライザで接続するときに頭に「tcp:」をつけて何とかなりました。ふぅ、よかった。

Orca

ここ にあった記事によると、Platform SDK をインストールしなくても、Orca がダウンロードできます。Platform SDK はでっかいので、Windows Installer の中身をのぞきたいときは、これだけで十分ですね。


2005-01-15

Classic

日々、ちょこまかコードを書いたりしているわけですが、使い捨てなわけです。一部のコードは再利用したりしますけど。どんどん生産され、どんどん消費されていくコード。もう少しなんとかならないのかな、って思います。

ときたまクラシックを聞きますが、その曲自体は下手すると何百年も前に書かれたものだったりするわけで。それをいろんなアレンジ、いろんな解釈で再度演奏すると。

クラシックのようなプログラム。そんなのは無理だろうなぁ。


2005-01-14

When do you check it?

とある ML でのやりとりですが、API を使ってデータを取得し、結果をファイルに書き出しているとのこと。で、出力結果が期待値と異なるので、原因を探っていると。

手順としては、以下のような感じだそうです。

  1. API でデータを取得
  2. さらに API でデータを加工
  3. 加工したデータをファイルに出力

そもそも、期待値が得られないのであれば、1 から順に状態を探っていくものだと思うんです。3 の段階でおかしいとしても、3 が悪いのか、2 が悪いのか、1 が悪いのかと、3通りの原因が考えられるわけですし。

なんというか、「切り分け」とか「順を追って」とか、そういう基本的なことがおざなりにされているなぁ、と思いました。


2005-01-13

Nile

Visual Basic .NET で作られた Web アプリケーションのサンプル Nile 4.0 をダウンロードしてみました。かなりシンプルに作られています。これをいろいろ調べてみたいと思います。

DOA+ Consortium

DOA+ Consortium ですか。会員登録したけど、分科会アクセス用の ID とパスワードが届かない...。

Model and ...?

モデルの責任について考えてたんですが、どこまでをやるべきなのか。単なる入れ物でいいのか、データのやり取り辺りまで責任を持つべきなのか。

そう考えていたら、モデルの大きさにも疑問が出てきました。たとえば、顧客を示す Customer モデルってのを作ったとします。簡単なものならいいんですが、実際のシステムで使うレベルで考えると、かなりいろんなものを含むわけです。

たとえば、顧客の名前、住所、売り上げ、などなど。ここで、顧客の名前を修正したいという画面を考えてみます。そのとき、たとえば売り上げに関する情報は不要になります。しかし、Customer モデルとしてクラスにしてしまうと、不要なデータまでやり取りすることになってしまいます。

...では? Customer を基本として、CustomerAddress、CustomerSales、CustomerSomething と、次々にクラスを作っていけばいい、ということになるんでしょうか...。


2005-01-12

Subversion on NTEmacs

Emacs 上で Subversion クライアントが動くそうです。で、さっそく Cygwin の Subversion をインストールしたのですが、何かやろうとすると "svn: Can't recode string" と。調べてみると、文字コードの関係のようです。LANG=ja_jp.UTF-8 で OK という話もありましたが、どうもだめ。かなりイヤンな感じです。


2005-01-11

Andale Mono or Osaka?

等幅フォントに、最近 Osaka を使うようになりました。今までは、ずっと Andale Mono を使ってきて、このサイトでも <pre> タグの中に指定しています。しかし、前から気になってはいたのですが、<pre> タグ内の一行目が微妙に左にズレるのです。

.css の書き方にミスがあるんだろ、ぐらいに思って、とりあえず放っておいたのですが、どうにも気になってしまって、仕方がありません。ということで、いろいろ試してみると、やはり Andale Mono のときのみズレます。所詮、自分用のチラシの裏みたいなサイトですから、自分の環境できれいに見えることが重要です。そう考えて、<pre> タグのフォントを Osaka に変えました。

Windows で Osaka フォントの入っている、ちょっと特殊な環境に最適化されたサイトだったりします。

Subversion Memo - 2

ふと、別プロジェクトを追加してみると、リビジョンが増えて...。あら? だめじゃん。そうか、プロジェクトごとにリポジトリを作る形になるわけね。

しかし、だとすると、その度ごとに apache2 側の設定が必要になるわけです。これは面倒だなぁ。ということで、しょぼいスクリプトを作りました。ディレクトリの作成、SVN ディレクトリの作成、初期ディレクトリの作成、インポート、/etc/apache2/apache2.conf に情報追加、apache の再起動までガガガっと。

あとは、SVNReposName "リポジトリ名" を指定するようにして、Web で見たときにプロジェクト名が表示されるように。最後に、.xsl と .css を編集して、見た目をちょっとだけ改造。ひとまず、これでテスト運用してみようっと。

Subversion Memo

昨日のやり方だと、ちょっと気に入らないところが出てきたので、修正をしてみる。

  • パスを変更
  • 見た目を変更

Subversion への接続方法が hostname/svn/repos/ となってしまっていたので、Location を変更して hostname/svn/ でアクセスできるようにした。

見た目がちょっとさびしいので、ソース tar から .xsl、.css を持ってきて、読み込むように指定。


  <Location /svn>
    DAV svn
    SVNPath /var/svn/repos
    SVNIndexXSLT "/svnindex.xsl"
  </Location>

  • Virtual Directory を止める (コメントアウト)
  • Document Root の指定

  # /etc/apache2/apache2.conf

  #Include /etc/apache2/sites-enabled/[^.#]*
  DocumentRoot "/var/www/"

  • レポジトリディレクトリの変更

解説では、branches, tags, trunk の 3つのディレクトリを作成するようになっている。また、これらを Subversion のルートディレクトリに作ってしまうので、


  - create directory and import to repository
  
  $ mkdir /tmp/svnroot/projectname
  $ cd /tmp/svnroot/projectname
  $ mkdir develop release

  $ svn import /tmp/svnroot/ file:///var/svn/repos/ -m "Initial Import"

として、svn/ の下にプロジェクトを。プロジェクトの下に develop と release ディレクトリとなるようにした。

  • 接続時に BASIC 認証を行う

  - create user

  $ htpasswd -cm /etc/svn-auth-file ユーザー名

2 人目以降のユーザーを追加するときは、「-c」オプションを外す。「-c」をつけると、ファイルを作りなおしちゃうので。


  # /etc/apache2/apache2.conf

  <Location /svn>
    DAV svn
    SVNParentPath /var/svn/repos
    AuthType Basic
    AuthName "Subversion repository"
    AuthUserFile /etc/svn-auth-file
    Require valid-user
  </Location>


2005-01-10

Install Subversion

例によって例のごとく、


  - install and initial settings

  $ sudo apt-get install subversion
  $ sudo apt-get install apache2
  $ sudo apt-get install libapache2-svn

  $ sudo mkdir -p /var/svn/repos
  $ sudo svnadmin create /var/svn/repos
  $ sudo chown -R www-data:www-data /var/svn

  $ mkdir /tmp/project
  $ cd /tmp/project
  $ mkdir branches tags trunk
  $ cd trunk
  $ touch hoge.c

  $ svn import /tmp/project/ file:///var/svn/repos/ -m "Initial Import"

で、インストールと (最後のは必要かどうかわかりませんけど)。設定関連は、この辺 を見ながら。無事ローカルにレポジトリができました。よしよし。一応、svn のクライアントからも接続できます。

あとは、/etc/apache2/apache2.conf に、以下の内容を追加、と。これで、Web ブラウザからもアクセスできるようになりました。


  # /etc/apache2/apache2.conf

  <IfModule mod_dav.c>
    DAVLockDB  /var/lock/DAV/DAVLock
  </IfModule>

  <IfModule mod_dav>
    Dav on
  </IfModule>

  <Location /svn/repos>
    DAV svn
    SVNPath /var/svn/repos
  </Location>

AnkhSVN: A Subversion addin for Microsoft Visual Studio .NET をダウンロードしてきて、インストールと。インストールの最後になんかエラーが出て、デバッガが立ち上がっていましたが、とりあえず問題はない模様。Visual Studio 2003 からも接続できるようになりました。ふぅ。

追記: AnkhSVN ですが、日本語がぼろぼろでした...。TortoiseSVN は Unicode 版ということもあってか、いい感じです。

DB FrontEnd Pattern - Objective

目標をまとめておかないといけませんね。ありきたりですが、以下のようなことを目的にしています。

  1. コードが見通しやすいこと
  2. 再利用しやすいこと
  3. 修正しやすいこと


2005-01-09

DB FrontEnd Pattern

MVC は使いづらいってことで、じゃ、どうすればいいのでしょうか。これといった代案があるわけではないのですが、今までに作ってきたアプリケーションを振り返って、ちょっとまとめてみようかと。あ、もちろん、MVC も使いどころによってはいいもんですし、全否定するつもりはありませんので。

  1. データアクセスクラス
  2. モデル
  3. ユーティリティクラス
  4. フォーム
  5. 継承フォーム
  6. 複合コンポーネント

まず、データアクセスを行うクラスはまとめておいた方がいいです。つか、これ必須です。考えなしに、ウィザードにお任せで作っていくと、データアクセス関連の処理がわさわさできてきちゃいます。なので、データベース接続、トランザクション管理などは、この辺のクラスできっちりやると。

モデルは、データベースから取得したデータをクラスにマッピングし、アプリケーション側で使いやすくするためのものです。いわゆる O/R マッピングに伴うインピーダンスミスマッチが発生したりと、ややこしい問題を内包しています。1:1 ならいいんですけど、たとえば数百件、数千件を結果セットに取得したとき、これを本当にマッピングするのか? ってことにもなります。当然、O/R マッピングにもコストがかかりますから。

ユーティリティは、いろんなことをするためのクラスです。旧 Visual Basic 時代における、共通関数から進化してきたものにあたります。そういえば、以前「共通関数として使いたいから」という理由で、こういうユーティリティクラスを継承したフォームを見たことがありました。かなり萎え萎えになった記憶があります。

Emacs 21.3.50 --xrm Command line parameter

へー。こんなのができるようになってたんだ...。こりゃいい感じ。バッチファイルでは、バックスラッシュによる改行が効かないみたいなので、一行に書いてみてください。


  emacs
    --xrm "Emacs.background:black" \
    --xrm "Emacs.foreground:white" \
    --xrm "Emacs.Geometry:84x42+250+30" \
    --xrm "Emacs.Fontset-0: \
      -*-Osaka-*-r-*-20-*-*-*-*-c-*-fontset-osaka20c, \
      ascii:-*-Osaka-normal-r-normal-*-20-*-*-*-c-*-iso8859-1, " \
      japanese-jisx0208:-*-Osaka-*-*-*-*-20-*-*-*-c-*-jisx0208-sjis, \
      japanese-jisx0212:-*-Osaka-*-*-*-*-20-*-*-*-c-*-jisx0208-sjis, \
      katakana-jisx0201:-*-Osaka-*-*-*-*-20-*-*-*-c-*-jisx0208-sjis, \
      japanese-jisx0208-1978:-*-Osaka-*-*-*-*-20-*-*-*-c-*-jisx0208-sjis"
    --xrm "Emacs.font:fontset-osaka20c"
    --line-spacing 3

MVC

伝統的な MVC の形からすると、

  1. Model - データを保持する
  2. View - 表示を行う
  3. Controller - 入力を受け、Model と View を操作する

という感じになってるわけです。しかし、いわゆる Windows Forms 系のアプリケーションの場合、入力部分と表示部分が密接に絡んでしまう、と。View と Controller の分離で、いきなり困ってしまいます。

さらに、データベースのフロントエンドアプリケーションの場合、複数の View を持つことはかなり稀です。Model というか、データセットとフォームが 1:1 の関係にあることがほとんどです。ここで、MVC の大きなメリットのひとつである、View が交換可能という点が意味を持たなくなってしまいます。

なので、MVC にこだわるよりも、何か別の形を検討したほうがいいのかなぁ、と思うようになりました。


2005-01-08

Sleep

起きたら夜の 8時でした。何だこりゃ。


2005-01-07

Emacs Hack

やっぱり気になるので、どうして 2バイト文字がフォント名に含まれていると表示できないのか、確認してみることにしてみました。で、見ていくと Emacs 内部形式から Shift-JIS に変換しているところに問題があるようです。IPA ゴシックを指定しているはずが、IPA ゴシャク? うーん、XFLD 形式を変換して、CreateFontIndirect() APIでフォントを生成するまでのどこかに、問題があるようなんですが...。まだ追いきれてません。


2005-01-06

The Liskov Substituion Principle: LSP

デザインパターンの ML で出ていた話題でちょっと気になったのですが、「リスコフの置換原則」というものがあるそうです。その内容は、「派生型はその基本型と置換可能でなければならない」らしいのですが...。

ぱっと読んで、「どうもおかしいなぁ」と思ってしまいました。例として、長方形を示す Rectangle クラスと、そのクラスから派生した、正方形を示す Square クラスが挙げられています。

LO.GS*DI.GS というサイトに、ちょっと詳しい説明があったので引用させてもらうと、

派生クラスはその基本型が持っているすべてのメソッドの振る舞いの妥当性を維持しなければいけないということである。例として、Rectangle(長方形)が、setWidth(幅の設定)とsetHeight(高さの設定)というメソッドを持っていた場合を考えてみる。Rectangleの派生型として、Square(正方形)を考えた場合、幅と高さを同じにすることが必要であり、setWidthとsetHeightでバラバラの値を設定することが許されなくなる。setWidth実行時にsetHeightを同じ値で呼び出す(またその逆も)ようにすると、値は同じに保たれるが、バラバラに設定できるという性質を失ってしまう。このことから、この原則は、クラスのみで成立するのではなく、周りとの約束(契約と呼ばれる)によって成立することがわかる。

つまり、利用者が、Square クラスの幅と高さを別々に設定できることを期待しても、それは不可能なわけです。当然、Square クラスは Rectangle クラスに置換することができないので、不味いということです。

え、でも、そういうことを言っていたら、たとえば、すべてのクラスの派生元である Object クラスから、他のクラスを派生させることもできないんですけど...。Object クラスから派生した Numeric クラスは、数値を示します。当然、文字列などを示すことはできません。何でも OK の Object クラスと置換することはできないわけです。

今日の役に立たない一言 − Today’s Trifle! − に、元の文章の結論が引用されていましたので、孫引きになってしまいますが、引用します。

「IS-A」という用語は、派生型の定義として用いるには意味が広すぎる。派生型の本当の定義は基本型と「置換できる」ということなのだ。「置換できる」の内容は、明示的な契約、または、非明示的な契約によって定義される。

前の引用にも書かれていますが、どうもポイントは「契約」にあるようです。何かよくわからないのですが、先ほどの Square クラスの例で言えば、「高さと幅は異なってはいけない」という契約の元に派生し、その契約の元で利用されるのであれば、問題ないということでしょうか。

だとしたら、「置換可能でなければならない」なんて、誤解を招くような言い方はやめて、「派生クラスがサブセットであるときは、その差異を明確に (あるいは、契約によって制限) すべき」とでもすればいいのに。

まぁ、読み違えてる可能性大なのですが、Square が Rectangle と違って、高さと幅を別々に設定できない、なんてのは「非明示的な契約」ではないんでしょうかね。読み違いだったとしても、適切な例とは思えません。

Emacs 22

噂には聞いていたけど、試したことはなかったので、CVS から Emacs22 のツリー (emacs-unicode-2) を落としてきてビルド。Emacs 21.3.50 用のパッチがすんなり当たって、おっ? と思ったのもつかの間、やっぱりビルド時にエラー。そりゃ、そうですよね。

とりあえず、IME パッチなしの状態ではビルド OK。フォントセットの指定時にお亡くなりになりました。そこを直すと、今度は Tab 補完で落ちまくります。まだちょっと安定まではかかるのかなぁ。

とりあえず、SKK をインストールしてみましたが、問題なく? 動く模様。しかーし、SKK の使い方をすっかり忘れてるし...。leim でいいかな、なんて日和ってみたり。


2005-01-05

T-SQL Modules

二日ほど前の記事ですが、急に TSQLUnit について調べてみようと思いたったわけではなく、T-SQL でストアドプロシージャを作成するにあたって、ストアドをどのように分ければいいのかな、ということについて考えていました。

そのストアドというのは、定期的に SQL Agent から起動され、不正なデータがないか調べるというものです。また、調べた結果をファイルとして出力し、その内容を指定のアドレスにメールとして送信するというわけです。

まぁ、いろんな実現方法があるわけですが、今回はコマンドプロンプトの機能と、BASP21 によるメール送信を xp_cmdshell で動かそうと考えました。で、最初はひとつのストアドプロシージャとして作ったわけですが、よくよく考えてみると、かなりの部分が共通化できそうです。たとえば、

  1. 不正データをテンポラリテーブルに抽出
  2. テンポラリテーブルの内容をファイルに出力
  3. ファイルの内容をメール送信

といった具合です。さらに言えば、前処理だとか後処理だとかも共通化できるというわけです。...と、このような前提の上で、どのようにモジュール分割するのがよいかな、と。クエリアナライザってツールは、その辺は積極的にサポートしていませんので、せいぜい接頭辞をつけてグループ化するぐらいしかなさそうです (そのためにデータベースを分ける、ってとこまでやると、本末転倒ですし)。

ツールが積極的にサポートしていない、イコール、自由度が高すぎる、ということでもあります。何かいい方法はないものかなぁ...。


2005-01-04

Font Probrem

もしかして、と思ったら、やっぱりそうでした。そもそも、元の状態で正しく表示されないのは、フォント名に 2バイト文字が入っていたからのようです。ということで、フォントの書体名を変更してとりあえず OK と。

このツールを探すのに、えらい手間取ってしまいました。ここ からダウンロードできます。

Emacs 21.3.50 font

あらら。ひとつ前の記事の方法だと、スケーラブルフォントが表示されないでやんの...。表示されないというか、フォントサイズの変更が効かないです。やっぱり、手抜き Hack はダメダメですな。うーん。困った...。

Memo

MVC について、再度考えてみようと思う今日この頃。デスクトップ主体のデータベースフロントエンドを作ってきた人間にとっては、MVC ってやっぱり違和感があるなぁ。

Emacs 21.3.50 compile

いつものごとく、お手軽 Hack、と。フォントがいまいちしっくり行かなかったんで悩んでいましたが、とりあえず、以下の修正で問題なくいけてるみたいです。文字幅も揃ってるし、いい感じ。

cvs 版も同じ修正で動きました。man を作る辺りがうまく行かなかったので、makefile をいじりましたけど。これをベースに、.emacs の移植を始めようっと。


  *** emacs2135/src/fontset.c.old   Tue Nov  9 10:35:09 2004
  --- emacs2135/src/fontset.c.new   Mon Jan  3 23:02:40 2005
  ***************
  *** 630,636 ****
        return Qnil;

      return font_family_registry (build_string (fontp->full_name),
  !                    SINGLE_BYTE_CHAR_P (c));
    }


  --- 630,636 ----
        return Qnil;

      return font_family_registry (build_string (fontp->full_name),
  !                    0); //SINGLE_BYTE_CHAR_P (c));
    }


2005-01-03

TSQLUnit

モジュールについていろいろ考えながらさまよっているうちに、T-SQL 用の xUnit フレームワーク を見つけました。まだ、試してませんけど。で、クックブック として、その使い方が説明されていましたので、以下、なんとなく翻訳。当然のことながら、意訳です。変だな、という部分はオリジナルを参照してください。

TSQLUnit cookbook

この小さなクックブックでは、TSQLUnit を利用したテストについて、その手順を説明します。

Why?

ストアドプロシージャを開発するとき、ほとんどの T-SQL 開発者はクエリアナライザ上で PRINT ステートメントと手動によるテストの組み合わせを使うと思います。一部の人は、変数の値を調査するために、T-SQL デバッガを使うでしょう。どちらの場合も、結果を分析するために「人」の判断が要求されます。そのため、手動によるテストは、簡単に繰り返すことができません。TSQLUnit または、その他の xUnit フレームワークによるテストであれば、このような不都合はありません。テストには、以下のようないくつかの利点があると信じています。

  1. テストは、何度も繰り返すことができます。よいテストは、何かを壊すことを恐れずにコードの品質を改善できるよう、あなたに勇気を与えるかもしれません。コードの品質を改善することは、「リファクタリング」と呼ばれます。
  2. テストのためのストアドプロシージャは、ドキュメントとしての意味も持ちます。テストプロシージャは、実際のストアドプロシージャの中で何が行われるかを説明します。
  3. ストアドプロシージャを書く前にテストを書くと、そのインターフェースについて注意深く考えることになります。それにより、デザインは改善されるかもしれません。

テストは、eXtreme Programming - それはソフトウェア開発の多くの伝統的な問題を解決しようと試みるものです - と呼ばれる方法論のかなめの1つです。あなたは、http://www.xprogramming.org/ あるいは http://www.extremeprogramming.org/ で、それについてもっと読むことができます。

How?

TSQLUnit でテストを行うときは、次のようにしてください。

  1. ut_testSomethingというように、ut とアンダースコアで始まる名前のストアドプロシージャを作って下さい
  2. テストプロシージャを作成します。もしテストが失敗したときは、tsu_failure ストアドプロシージャを呼び出してください
  3. tsu_runTests ストアドプロシージャを実行して下さい。それは、あなたが作ったテストを実行して、そして結果を表示します

この例では、文字列をキャピタライズ(文章の最初の単語の最初の文字を大文字に変換)するストアドプロシージャをテストします。


  CREATE PROCEDURE ut_testCapitalize AS
  BEGIN
    DECLARE @outStr VARCHAR(500)
    EXEC capitalize 'a string', @outStr OUT
    IF (ASCII(LEFT(@outStr,1)) <> ASCII('A')) OR @outStr IS NULL
      EXEC tsu_failure 'Capitalize should make the first character uppercase'
  END

このテストに加えて、より多くのテストを作ることをお勧めします。文字列が NULL だった場合や、多くの文章を渡した場合のテストなど。あなたが同じようなテストを作るとき、テーブルと他の入力データのために、しばしば同じコードを使います。そのようなケースでは、Fixture を作った方がよいかもしれません。

Test Suite

tsu_runTests ストアドプロシージャは、デフォルトですべてのテストを実行します。テストの数が多くなると、テストには長い時間を必要とするかもしれません。同じようなテストはまとめて行いたいものですし、それによりテストがグループ化できます。これは、オブジェクト指向の xUnit フレームワークでは、同じ TestSuite クラスにテストメソッドを作成することで実現できます。TSQLUnit では、テストの名前に共通の接頭辞を加えることによって、テストをひとまとめにすることができます。

ut_CapitalizeOneSentence、ut_CapitalizeWithNull と ut_testCalcSalesForAllCustomers という 3つのテストがあり、最初の 2つが関連したものだとします。最初の 2つと、実行に時間がかかる 3つ目のテストを別々にテストするには、最初の 2つのストアドプロシージャを、それぞれ ut_capitalizeTests_oneSentence と ut_capitalizeTests_withNull という名前に変更してください。テストスイートには、「capitalizeTests」という名前をつけます。このスイートをテストしたければ、tsu_runTests「capitalizeTests」を実行してください。

Fixture

多くの場合テストには、あらかじめデータを用意しておかなければなりません。このための仕組みは「Fixture」と呼ばれます。Fixture は同じようなテストプロシージャの間でしばしば共有されます。これにより、プロシージャは小さく簡潔になります。TSQLUnit では、「setup」と呼ばれる特別のプロシージャを作ることで、テストスイートに Fixture を加えることができます。

setup プロシージャは、テストスイートでそれぞれのテストの前に実行されます。setup プロシージャとテストプロシージャは、トランザクション後にロールバックされます。そのため、テストの実行順序を心配する必要はありません。また、それ以前に実行されたテストが Fixture を変更してしまう、いかなる危険もありません。

「CapitalizeTests」テストスイートに Fixture を追加するために、ut_capitalizeTests_setup と呼ばれるストアドプロシージャを作成してください。

もし、自動的にロールバックされない何かを明示的にクリーンアップする処理が必要なときは、「teardown」というストアドプロシージャを作成します。この例では、ut_capitalizeTests_teardown という名前になります。teardown プロシージャが役に立つ例としては、setup プロシージャでファイルを作成したような場合です。トランザクションがロールバックされても、ファイルは削除されません。そのため、teardown プロシージャで削除する必要があります。

ここに setup プロシージャを使ったもう少し長い例があります。テストの目的は、Northwind データベースの SalesByCategory プロシージャにおいて、割引あり/なしのそれぞれの場合で、計算が正しく行われているかどうかの確認です。2つのテストケースで、それをテストします。SalesByCategory プロシージャのクエリは、4つのテーブルからデータを取得します。これらのテストケースで利用されるデータを準備するために、Fixture を使うことができます。プロシージャの擬似コードは、以下の通りです。完全なコードは、ここ を参照してください。


  CREATE PROCEDURE ut_salesbycategory_setup AS
  BEGIN
    -- 1. Remove foreign key constraints related to for the
    --    tables Categories, Products and Orders.
    --    This makes it easier to clear the tables and insert testdata.
    -- 2. Delete all existing data for the tables Categories,
    --    Products and Orders.
    -- 3. Insert one row of test data for each table
  END


  CREATE PROCEDURE ut_salesbycategory_noDiscount AS
  BEGIN
    -- 1. Create a variable @ok that will hold the result of the test.
    -- 2. Clear all data from the table [Order Details].
    --    Insert a new row in
    --    [Order Details] with UnitPrice=100 and Quantity=10
    -- 3. Execute SalesByCategory
    -- 4. If the returned TotalPurchase is 1000 (UnitPrice*Quantity),
    --    set @ok to 1
    -- 5. If @ok is zero, Execute tsu_failure
  END


  CREATE PROCEDURE ut_salesbycategory_discount AS
  BEGIN
    -- Do exactly as ut_salesbycategory_noDiscount,
    -- but add a discount of 30 percent
    -- to the row in [Order Details].
    -- Test that SalesByCategory is 700 (70 percent of 1000).
  END

Some suggestions

ひとつのテストでは、ひとつのテストのみを行うようにします。

式が NULL のとき、T-SQL での比較演算子の働きに注意してください。上記の ut_salesbycategory_noDiscount プロシージャの @ok 変数のパターンは、テストが正しいときを除いてすべてのケースで失敗するので、この問題を解決します。

テストケースが増えるごとにリファクタリングしてください。テストケースが何を行うかを理解しながら確認してください。

テストを書くことが難しいときは、インターフェースのデザインを変えるか、リファクタリングを行うサインです。

実行環境でテストを実行しないで下さい。 TSQLUnit がテストプロシージャによって行われた変更をロールバックしたとしても、それが確実であるとは限りません。この世からバグがなくなるまで、このことに注意して下さい。もし危険を感じたら、テストを実行する前にバックアップを取るか、あるいは、データベースのコピー上で実行すべきです。


2005-01-02

Mail address

このサイトのメールアドレスは webmaster@antoine.st にしてあるんですが、なんと、いまさらながら、そのメールをチェックしていないことに気づきました。今のところ、ウィルスぐらいしか届いていないみたいですが、かなりイヤンな感じ。

ちゃんと設定をして、巡回チェックするように設定、と。

Diet Log

全然更新していなかった DietLog ですが、何気に 74.8 kg になってました。やっぱり、お薬 (しかも、ちょっとヤバめの) を使うと違うなぁ...。

Lady Godiva

チョコで有名な Godiva。その社名の由来となった絵を見つけた (正確には、由来となったお話を題材とした絵、ですな) ので、なんとなく リンク。へー。こんな があったんですか。

emacs 21.3.50

かなりよくなっているという噂を聞いたので、バイナリ を取ってきて試してみることに。うーん。今までの .emacs がボロボロ。特にフォントの設定が全然ダメなのが致命的。もう少し調べてみることにしましょう。

追記:

  • いろいろとやってみたところ、それなりにはなりました。が、全角半角 2:1 が実現できず、断念。うーん、むずかしい。どこぞで耳にしたとおり、フォントの検索方法がかなり厳しくなっている模様。


2005-01-01

RSS

さっそく微調整。おかしいなぁ。前まで問題なかったと思うんだけど。

「Emacs ユーザーは、Emacs で何をしているの?」「.emacs をいじるに決まってるじゃん」というお話がありますが、まさにそのまんまだったり...。

New Year

明けましておめでとうございます。ということで。

去年はいろいろあった一年でした。後半、ぼろぼろでしたけど。今年はどんな年になるのやら。すでに、いくつかイベントが予定されているので、ひと波乱ありそうです。

とりあえず、リハビリもかねて、のんびりと更新していきたいと思います。あいかわらず、大した内容はないんでしょうけどね。

おっと。さっそくフッターを直しておかないと。