はてなアカウント引っ越し計画
はてなアカウント引っ越ししようと思います。
引っ越し先のブログ(下記URL)を更新したので、お知らせです。
http://d.hatena.ne.jp/jote/20100908/1283963804
しばらくはこのままですが、いずれこのブログは削除します。
ご迷惑をおかけします。
Ruby3 ユニットテストのレビュー
Ruby3は読んでいて、ストーリーがしっかりしているから面白い。
この項目の流れも面白かった。
四則演算の簡単なプログラムを書いて、それをテストしていくお話。テストは始め自作する。すると、同じようなメソッドを何回も書くことになり、前章で勉強したフレームワークを使うことになる。この話の流れが上手いなと思った。同じようなメソッドを書いているので、フレームワークがとてもありがたい。
- 利用するフレームワーク:Ruby標準添付のMiniTestというテスティングフレームワーク
- テスト用クラスは、Test::Unit::TestCaseクラスを継承する
- テストメソッドは、メソッド名の頭にtestとつける
- Test::Unit::Testcase > MiniTest::Unit::Testcase
- テストメソッドの実行方法
begin setup() method() rescue ensure teardown() end
- テスト結果の検証・失敗時の表示には表明メソッドを使用
ユニットテストの勉強
Ruby3 第6章を読んでみたので、覚書。
ユニットテスト
- プログラムを開発するためのツール
- 開発したプログラムの単体機能検証
- ある1つのプログラム・ライブラリ・クラスが仕様を満たしているか
ユニットテストが持つ「ツール」と「単体機能の検証」の2つの意味に混乱した。
要するに、パーツをテストしながら作成して、最後に全体の動作をテストするってことでしょうか。
ユニットテストプログラムとは
ユニットテストについて詳しく説明されてたのでメモ
- プログラムが正しく動作しているか確かめるプログラム
- プログラムと同時・先行して作っていく
- テストを書きやすくするために、プログラムは読みやすいようにする
簡単なwebサーバをプログラムで書いてみた
「ruby3 5章1 簡単なWebサーバーのプログラミング」を読んだのでレビュー
目次
- ソケットの利用
- HTTPリクエストの内容
- HTTPレスポンスの内容
- Webサーバの仕組み
HTTPレスポンスの内容
HTTPレスポンス構造の説明がある。読んでて面白かったのは、HTTPの主なステータスコート・カテゴリ・メタデータを簡単に紹介しているところ。200・301・404・503など身近なステータスコードが説明されている。
Webサーバーの仕組み
HTTPリクエスト・HTTPレスポンスの動作確認をしたところでWebサーバーの仕組みについて説明。TCPSocketとTCPServerを説明した図があるのだけれど、よくわからなかった。クライアントとサーバーの動きを図示しているが、動きの説明がなく図を見て理解するしかない。ここも説明あると嬉しい・・・
プログラミング
フォームに文字を入力し、その文字が表示される簡単なwebサーバを書いた。
1 # encoding: cp932 2 3 require "socket" 4 require "uri" 5 6 def header(data) 7 map = {} 8 data.scan(/([^:]+):\s*(.+)\s*\r\n/) do |k, v| 9 map[k] = v 10 end 11 map 12 end 13 14 TCPServer.open(8000) do |server| 15 loop do 16 sock = server.accept() 17 data = "" 18 begin 19 data << sock.read(1) 20 end while !data.index("\r\n\r\n") 21 reqline = data[0...data.index("\r\n")] 22 metadata = header(data[reqline.size + 2..-3]) 23 body = nil 24 if metadata["Content-Length"] 25 body = sock.read(metadata["Content-Length"].to_i) 26 name = URI.decode(body.match(/name=(.*)/)[1]) 27 break if name == "end" 28 end 29 resp = "<html><body>" 30 if body 31 resp << "<div>hello #{name} !</div>" 32 end 33 resp << "<form name='form' method='post'>" 34 resp << "<input type='text' name='name'><input type='submit'></form>" 35 resp << "</body></html>" 36 sock.write("HTTP/1.1 200 OK\r\n") 37 sock.write("Content-Type: text/html; charset=Windows-31J\r\n") 38 sock.write("Content-Length: #{resp.size}\r\n") 39 sock.write("Connection: close\r\n") 40 sock.write("\r\n") 41 sock.write(resp) 42 sock.close() 43 end 44 end
これを改造してファイル名を指定し、内容を上に表示するプログラムに書き換えてみた。下記のopen_request_fileメソッドを追加。if metadata["Content-Length"]〜endを書き変え
def open_request_file(name) f = open(name, "r") content = "" f.each do |line| content << "#{line}<br>" end content end
24 if metadata["Content-Length"] 25 body = sock.read(metadata["Content-Length"].to_i) 26 name = URI.decode(body.match(/name=(.*)/)[1]) 27 break if name == "end" 28 end 29 # 下記のように書き換え if metadata["Content-Length"] body = sock.read(metadata["Content-Length"].to_i) file_name = URI.decode(body.match(/file_name=(.*)/)[1]) req_file = open_request_file(file_name) break if file_name.nil? end
RubyでクWebServerができたので、Tokyo Cabinetのクライアントみないなもの作ってみたい
shiftの罠
Array#shiftメソッドの仕様を気にせずに使っていたので、ハマった事を書きます。
配列をshiftしていって、空配列になった時。配列aは全ての要素が取り出された時、a = nilになると思っていました。
しかし、shiftは配列の要素を取り出すメソッドなので配列自身は消えないんですよね。よくよく考えれば気づくことなんだけど、今後注意しなければ。
irb(main):001:0> a = [1,2] => [1, 2] irb(main):002:0> a.shift => 1 irb(main):003:0> a.shift => 2 irb(main):004:0> a.shift => nil irb(main):005:0> a.nil? => false irb(main):006:0> a.empty? => true
nil?メソッドでtrueが返ってくるとおもってたのですが、配列自身は空配列になっている。
ブロック付きメソッドとyield制御構造
ブロック引数について書いた記事があったのですが、間違ってたのでその記事は消しました。
ごめんなさい。
まずは、ブロックについて、勉強やり直します。
- ブロック
- doからend 又は、{} で囲われた一連の式
class Each_test def initialize(a) @myarr = a end def each max = @myarr.size - 1 for i in (0..max) do yield(@myarr[i]) end end end test = Each_test.new([0, 1, 2]) test.each{|value| puts value}
この場合、{|value| puts value}がブロック。このブロックはeachメソッドの引数なので、ブロック引数という。
- Each_test#eachを実行
- 初期化の際に指定された配列@myarr = ["no", "no", "war"]が対象。
- yield(@myarr[i])より、@myarr[i]を引数にしたブロック{|value| puts value}を実行。
- value = @myarr[i]
- yieldの意味は「譲る」
私が読んでる参考書に「yield制御構造をメソッドの中で呼び出すと、そのメソッドにも与えられたブロックを実行する。」と書いてありました。この「ブロックを実行する」という動きがどうしても想像できなかった。ブロック引数というので、流れとして
と考えて大混乱してました。
テンプレートメソッドパターン
- 基底クラス
- 共通の処理を実装する
- 派生クラス独自の処理をからのメソッドとして定義しておく
- 派生クラス
- 基底クラスの空メソッドをオーバーライドする
※上記2つのメソッドはprivateをかけて、外部に公開しないようにする