HomebrewでMySQLをインストール

何だか一発で上手くいかなかったのでメモ。最終的にはこれでうまく行った。

# これが効いたかどうかわからない
sudo chown -R `whoami` /usr/local

brew install mysql

# インストール後の説明では mysql_install_db にいろいろオプション与えてるけど、無くてもよさげ。
cd /usr/local/Cellar/mysql/5.5.10
scripts/mysql_install_db

# 起動用
launchctl load -w /usr/local/Cellar/mysql/5.5.10/com.mysql.mysqld.plist


これ真似した http://solutions.treypiepmeier.com/2010/02/28/installing-mysql-on-snow-leopard-using-homebrew/

「定本 解析概論」の誤植 (P12)

定本 解析概論のP12下の方、

任意のq \geq nに対してI_n - a_q \geq \varepsilon.

となってるが正しくは

任意のq \geq nに対してl_n - a_q \geq \varepsilon.

だと思う。I_nじゃなくてl_n

古いほうの解析概論と、http://ja.wikisource.org/wiki/%E8%A7%A3%E6%9E%90%E6%A6%82%E8%AB%96/%E7%AC%AC1%E7%AB%A0/%E5%8F%8E%E6%9D%9F%E3%81%AE%E6%9D%A1%E4%BB%B6Cauchy%E3%81%AE%E5%88%A4%E5%AE%9A%E6%B3%95で確認した。

定本 解析概論

定本 解析概論

Capybara+Seleniumのユニットテストで使うブラウザを変更する方法

昨日 の続きです。

最新版(まだ開発版)のCapybaraを使うと簡単にSelenium経由でFirefoxを使ったユニットテストができると書きましたが、その仕組みが謎だったので調べました。

Seleniumで使うブラウザをFirefoxからChromeに変える

spec/spec_helper.rb に以下の設定を書きます。

require 'capybara/rspec'
Capybara.register_driver :selenium_chrome do |app|
  Capybara::Driver::Selenium.new(app, :browser => :chrome)
end
Capybara.javascript_driver = :selenium_chrome
  • Configuring and adding driversのところに書いてあります。
  • Sporkを使う場合、Spork.each_run do ... end の中に書いても、sporkプロセスを再起動しないと反映されないみたいです。

新しいSeleniumはどうやって動いているか

以前のSelenium (Selenium RC)の場合、RCのプロセスを先に立ちあげておく必要があったと思いますが(うろ覚え)、新しいSelenium (Selenium 2.0 and WebDriver)では特に面倒な設定・準備なしで使えるようです。

以下、CapybaraがどのようにSeleniumを起動しているか調べた事をまとめます。

まず、JavaScriptの試験をCapybara+Seleniumを使って行いたい場合、:js => true オプションを渡します。

 describe "POST /articles", :js => true do
  # ...
  end

  # または

  it "JSのテスト", :js => true do
  # ...
  end

Capybaraはこのオプションを見るとテストを実行するドライバを入れ替えます。javascript_driverのデフォルトは:seleniumです。

# capybara/lib/capybara/rspec.rb
      Capybara.current_driver = Capybara.javascript_driver if example.metadata[:js]

CapybaraのSelenium driverは、selenium-webdriverというライブラリを使ってSeleniumを操作します。これはSeleniumの新しいAPIを使ったライブラリのようです。詳しくはSeleniumの本家にいろいろ書いてあります。

ここで、Seleniumで使うブラウザのデフォルトは:firefoxになっています。

# capybara/lib/capybara/driver/selenium_driver.rb
require 'selenium-webdriver'

class Capybara::Driver::Selenium < Capybara::Driver::Base
  DEFAULT_OPTIONS = {
    :resynchronize => true,
    :resynchronization_timeout => 10,
    :browser => :firefox
  }

ついでに selenium-webdriver を眺めてみると、他にもいろいろなブラウザに対応したドライバがあります。

# selenium-webdriver/lib/selenium/webdriver.rb

module Selenium
  module WebDriver
    Point     = Struct.new(:x, :y)
    Dimension = Struct.new(:width, :height)

    autoload :Android, 'selenium/webdriver/android'
    autoload :Chrome,  'selenium/webdriver/chrome'
    autoload :IE,      'selenium/webdriver/ie'
    autoload :IPhone,  'selenium/webdriver/iphone'
    autoload :Remote,  'selenium/webdriver/remote'
    autoload :Firefox, 'selenium/webdriver/firefox'

まとめ

  • Capybaraの開発版を使うとSeleniumを使ったテストが簡単に使えます。
  • テストに使うブラウザを変えたかったらspec_helper.rbで設定を変えられます。
  • iPhoneAndroidに対応したドライバもあるようです。

RSpec+Capybara+SeleniumでJavaScriptのテスト

WEB+DB PRESS Vol.61の「Rails3テスト最前線」が話題のようです。
最新のRailscastsでちょうどRequest Specs and Capybaraが取り上げられていたので、WEB+DB PRESSの記事に載っていない部分を簡単にまとめてみます。

関連記事: WEB+DB PRESS vol.61 Rails3テスト最前線がすばらしい - tech-kazuhisa's blog

結論から言うと

Capybaraの最新版を使うと、SeleniumJavaScriptのテスト簡単に書けます。

やり方

Gemfileで、capybaraの最新版を使うようにgitリポジトリを指定します。JavaScriptとDBを同時に使う機能のテストをする場合はdatabase_cleanerも必要です。

group :development, :test do
  gem 'rspec'
  gem 'rspec-rails'
  gem 'capybara',  :git => 'git://github.com/jnicklas/capybara.git'
  gem 'database_cleaner'
end

spec/spec_helper.rbでcapybara/rspecを読み込みます。

require 'capybara/rspec'

database_cleanerを使う場合はspec/spec_helper.rbに設定を追加します。Seleniumを使ったテストを行う場合、デフォルトの "use_transactional_fixtures = true" ではDBを使ったテストは失敗します。

    config.use_transactional_fixtures = false # for selenium

    config.before(:suite) do
      DatabaseCleaner.strategy = :truncation
    end
    
    config.before(:each) do
      DatabaseCleaner.start
    end
    
    config.after(:each) do
      DatabaseCleaner.clean
    end

JavaScriptを使うテストに ":js => true" を付ければ完了です。テストはFirefoxで実行されます。*1

  describe "POST /articles", :js => true do
  # ...
  end

  # または

  it "JSのテスト", :js => true do
  # ...
  end

:js => true なテストはブラウザが立ち上がるのでとても遅いです。JavaScriptを使わないテストだけを実行したい場合は、

rspec -t '~js' spec

とすれば良いでしょう。(sporkを使うと -t '~tag' は無視されるような気がするけどなんでだろう)

おまけ

WEB+DB PRESSの記事には載っていないようですが、capybaraを使ったインテグレーションテストのひな形を生成するには以下のコマンドが使えます。(r は railsエイリアス、articleはテストするモデル名)

r g integration_test article

これを実行すると、spec/requests に下のようなファイルが生成されます。

require 'spec_helper'

describe "Articles" do
  describe "GET /articles" do
    it "works! (now write some real specs)" do
      # Run the generator again with the --webrat flag if you want to use webrat methods/matchers
      get articles_path
      response.status.should be(200)
    end
  end
end

サンプルコード

githubに置きました。

*1:Firefoxさえ入っていれば特に設定はいらないようです。仕組みは...謎です

やってみた: (1 2 3 4 5)が与えられたとき( (1 2) (2 3) (3 4) (4 5) )を返すような関数の定義

答え見ないでやってみた
vallog: [1,2,3,4,5] が与えられたとき [[1,2][2,3][3,4][4,5]] を返すような関数を定義せよ

#!/usr/bin/env gosh

(use srfi-1)
(use util.list)
(use gauche.test)

;; 1 だけならこれ
(define (slices* lis)
  (zip lis (cdr lis)))

;; 2 だとこれ。効率わるいかも。
(define (slices* lis :optional (n 2))
  (let loop ((lis lis) (r '()))
    (if (or (null? lis) (null? (cdr lis)))
      (reverse r)
      (loop (drop* lis (- n 1))
            (cons (take* lis n) r)))))

(test* "1"
       '((1 2) (2 3) (3 4) (4 5))
       (slices* (list 1 2 3 4 5)))

(test* "2"
       '((0 1) (1 2) (2 3) (3 4) (4 5) (5 6) (6 7) (7 8) (8 9))
       (slices* (list 0 1 2 3 4 5 6 7 8 9) 2))

(test* "3"
       '((0 1 2) (2 3 4) (4 5 6) (6 7 8) (8 9))
       (slices* (list 0 1 2 3 4 5 6 7 8 9) 3))

(test* "4"
       '((0 1 2 3) (3 4 5 6) (6 7 8 9))
       (slices* (list 0 1 2 3 4 5 6 7 8 9) 4))

答えみたけど素敵な解法いろいろある!

それよりtransposeってこんなに簡単に書けるのか!に感動した。

(define (transpose m)
  (apply map list m))

(transpose '((0 1 2 3)(4 5 6 7)(8 9 10 11)(12 13 14 15)))
;; -> ((0 4 8 12) (1 5 9 13) (2 6 10 14) (3 7 11 15))

数学勉強記録

4章むずい。しばらく別の本読んだ後、また4章からやり直そう。

線型代数学 (数学選書 (1))

線型代数学 (数学選書 (1))

Canvasでコッホ曲線描いてHerokuで公開してみた

id:keyesberry さんの記事 CanvasアニメーションをHerokuで公開しようよ! - hp12c を見て面白そうだったので作ってみました。

コッホ曲線を書くだけのものです。クリックすると細かい曲線になっていきます。ある程度までいくとまた粗くなっていって最終的に直線になります。ただそれだけ。

これ http://fractals.heroku.com/

アプリケーションの構成

JavaScript以外はほぼ丸パクリですが一応書くと

具体的なWebアプリケーションの作り方は id:keyesberry さんが詳しく書いてくれているのでそちらを参照して下さい。

以下、雑な解説。

fractals.js

メインのJavaScriptコードです。

var canvas = {};

$(document).ready(function() {
    canvas.c = $("#fractals");
    canvas.ctx = canvas.c[0].getContext('2d');
    canvas.width = canvas.c.width();
    canvas.height = canvas.c.height();

    canvas.ctx.save();
    clearCanvas();

    var iteration = 1, limit = 7, delta = 1;
    drawKoch(iteration);

    $(canvas.c).click(function() {
        clearCanvas();
        iteration += delta;
        drawKoch(iteration);
        if (iteration >= limit || iteration <= 0) {
            delta = -1 * delta;
        }
    });
});

function clearCanvas() {
    canvas.ctx.restore();
    canvas.ctx.clearRect(0, 0, canvas.width, canvas.height);
    canvas.ctx.save();
    canvas.ctx.translate(canvas.width/2, canvas.height*3/4);
}

この辺は元のコードとだいたい同じです。

座標系の変換を少し変えました。コッホ曲線のベースの直線をx軸上とし、またx軸をCanvasの下から1/4に置きます。
Canvas上の原点は左上でx軸、y軸の正の向きはそれぞれ右方向、下方向です。上のようにして変換後の原点がCanvasの中央、上端から3/4の位置にくるようにします。
Canvasのクリア方法ですが、座標を変換したままクリアするのは面倒なので、restore()で座標変換前の状態に戻してからクリアするようにしました。
jQueryでクリックイベントの処理を書きます。

function kochify(start, end) {
    var ps = trisect(start, end);
    var vertex = rotate60(ps[1], ps[2]);
    return [ps[0], ps[1], vertex, ps[2], ps[3]];
}

function trisect(start, end) {
    var p1 = [start[0] + (end[0]-start[0])*1/3, start[1] + (end[1]-start[1])*1/3];
    var p2 = [start[0] + (end[0]-start[0])*2/3, start[1] + (end[1]-start[1])*2/3];
    return [start, p1, p2, end];
}

function rotate60(start, end) {
    var v = [end[0] - start[0],
             end[1] - start[1]];
    var rotated =[ v[0] * Math.cos(-Math.PI/3) - v[1] * Math.sin(-Math.PI/3),
                   v[0] * Math.sin(-Math.PI/3) + v[1] * Math.cos(-Math.PI/3) ];
    return [ start[0] + rotated[0],
             start[1] + rotated[1] ];
}

function flatten() {
    var points = [];
    for (var i = 0, l = arguments.length; i < l; i++) {
        var ps = arguments[i];
        for (var j = 0, m = ps.length; j < m; j++) {
            points.push(ps[j]);
        }
    }
    return points;
}

この辺は補助関数です。
trisect()は始点と終点を受け取り、直線を3等分する4つの座標を返します。
rotate60()は同じく始点と終点を受け取り、それをベクトルと見て、60度回転した終点の座標を返します。回転行列を使う例のやつですね。
気を付けないといけないのは、y軸が下向きなため逆向きに(-60度)回転する必要があることです。はまりました。
変な名前のkochify()は、上の関数を使ってコッホ関数を描くのに必要な5つの座標を返します。

function drawKoch(iteration) {
    var left  = -canvas.width/2;
    var right = +canvas.width/2;

    var start = [left,0], end = [right,0];
    var points = koch(iteration, start, end);

    var ctx = canvas.ctx;
    ctx.strokeStyle = "black";
    ctx.lineWidth = 1;

    for (var i = 0, len = points.length; i < len - 1; i++) {
        var s = points[i];
        var e = points[i+1];

        ctx.beginPath();
        ctx.moveTo(s[0], s[1]);
        ctx.lineTo(e[0], e[1]);
        ctx.stroke();
    }
}

function koch(iteration, start, end) {
    var points = [];
    var recur = function(iter, s, e) {
        if (iter === 0) {
            points.push([start, end]);
        } else if (iter === 1) {
            points.push(kochify(s, e));
        } else if (iter > 0) {
            var ps = kochify(s, e);
            recur(iter-1, ps[0], ps[1]);
            recur(iter-1, ps[1], ps[2]);
            recur(iter-1, ps[2], ps[3]);
            recur(iter-1, ps[3], ps[4]);
        } else {
            throw "must not happen";
        }
    };
    recur(iteration, start, end);
    return flatten.apply(null, points);
}

drawKoch()はkoch()関数を呼び出して実際の描画を行います。koch()関数は点の座標を配列で返します。
koch()関数は、指定された回数に従って、線分を分割し再帰的に座標を計算します。変数pointsを破壊的に変更するのが何だか気に入らないかも。

以上、こんな説明で通じるかどうか分かりませんが終わりです。

ソースコードこのあたり


久しぶりにカビの生えた幾何学脳をフル回転させて楽しかったです。
サイト名がfractalsと複数形なのは、今後また他のフラクタル図形を描くかもしれないから。
本当はマンデルブロ集合を描きたかったけど、とりあえず簡単なのからやってみました。

マンデルブロGoogleの中の人がとっくにやってますけどね。