PhoneGapとSymfony2で始めるオフライン対応アプリ開発

2012年6月6日水曜日 投稿者 森怜峰 0 コメント

AndroidやiPhoneのブラウザではHTML5が全てサポートされているわけではないので、PhoneGapでブラウザの差を吸収しつつ、HTML5/JavaScriptで作成したものをアプリ化して、ネットワークに接続されていない状態でも使えるようにします。

HTML5単体でもApplicationCacheなどはあるものの、初回読み込みは必要なので、完全にオフラインで動作させることはできません。

Indexed DB APIはAndroid標準ブラウザでは使えませんので、オフライン状態でかつローカルのデータベースを使いたい場合はPhoneGapやTitaniumなどを使う必要があります。

今回はPhoneGapとjQuery Mobileを使用してオフラインアプリをAndroid向けに開発します。Android向けなんですが、たぶんiOSでも動作します。

ひとまずAndroidでビルドしてみます。
環境はMacですが、Windowsでもさほど変わらない(はず)


Android SDKのインストール

SDKのダウンロードはこちら http://developer.android.com/sdk/index.html


EclipseにADTプラグインを追加

Eclipseの Help > install new software から https://dl-ssl.google.com/android/eclipse/ このURLを指定する。

Android SDK ManagerでToolsとAndroidプラットフォームのSDKをインストール。


PhoneGapの導入

こちら http://phonegap.com/download からPhoneGap1.7を頂戴します。

で、このスタートガイドに従ってHello World的なものをやります。
http://docs.phonegap.com/en/1.7.0/guide_getting-started_android_index.md.html#Getting%20Started%20with%20Android

1. 適当にAndroidプロジェクトを作る
2. assets/www ディレクトリを作成する
3. libs ディレクトリを作成する
4. cordova-1.7.0.js を assets/www/ に配置
5. cordova-1.7.0.jar を libs/ に配置
6. PhoneGapの xml というフォルダを res/ に配置
7. JavaのBuild Pathのライブラリで、libs/cordova-1.7.0.jar を追加


Activityを書き換える

    package reoring.phonegap.test23;
    
    import android.os.Bundle;
    
    // PhoneGap
    import org.apache.cordova.*;
    
    public class PhoneGapTest23Activity extends DroidGap {
      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.loadUrl("file:///android_asset/www/index.html");
      }
    }

assets/www/index.html を書く

    <html>
      <head>
        <title>PhoneGap Test</title>
        <script type="text/javascript" charset="utf-8" src="cordova-1.7.0.js"></script>
      </head>

      <body>
  	    <h1>Hello PhoneGap on Android</h1>
      </body>
    </html>


jQuery Mobileを配置

assets/js/jquery.mobile に jQuery Mobileからダウンロードしてきたアーカイブを展開します。
jquery.mobile-1.1.0.css などがあればOK

HTMLを書き換え

    <!DOCTYPE HTML>
    <html>
      <head>
        <title>PhoneGap Test</title>
        
        <meta charset="UTF-8">
    
        <meta name="viewport" content="width=device-width, initial-scale=1">
        
        <link rel="stylesheet" href="js/jquery.mobile/jquery.mobile-1.1.0.min.css"/>
        <link rel="stylesheet" href="js/jquery.mobile/jquery.mobile.theme-1.1.0.min.css"/>
        
        <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script>
        <script type="text/javascript" src="js/jquery.mobile/jquery.mobile-1.1.0.js"></script>
        
        <script type="text/javascript" charset="utf-8" src="cordova-1.7.0.js"></script>
      </head>
    
      <body>
    
    	<div data-role="page">
          <div data-role="header">
            <h1>タイトルエリア</h1>
          </div>
    	
          <div data-role="content">
            <p>コンテンツエリア</p>
          </div>
    	
          <div data-role="footer">
            <h4>フッターエリア</h4>
          </div>
        </div>
      </body>
    </html>

これでひとまずPhoneGap上でjQuery Mobileが動作しました。

-------------------------------------------


Behat + MinkでATDDを実施

Symfony2のBehat Bundleで受け入れテストを日本語で記述して自動化します。
ブラウザの駆動ドライバとして今回はSahiを使います。

ATDD(Acceptance Test Driven Development)はその名の通り受け入れテストを自動化します。
受け入れテストをソースを書く前に記述して最終的な振る舞いを考慮しながら開発して手戻りを最小限にします。

受け入れテストは日本語で記述することによって振る舞いの確認をお客さんにして頂けるように考慮します。


Sahiのインストール

Tyto Softwareさんのページからダウンロードします。http://sahi.co.in/w/sahi-os-vs-sahi-pro

ダウンロードしたらインストールして、インストールディレクトリにあるsahi.shを起動します。
Macの環境だとbinに移動してからsahi.shを実行しないとなぜかエラーになるので注意してね。

正常に実行できるとコンソールに下記のようなメッセージがでます。

--------
SAHI_HOME: ..
SAHI_USERDATA_DIR: ../userdata
SAHI_EXT_CLASS_PATH:
--------
Sahi properties file = /Users/morireo/sahi/config/sahi.properties
Sahi user properties file = /Users/morireo/sahi/userdata/config/userdata.properties
Added shutdown hook.
>>>> Sahi started. Listening on port: 9999
>>>> Configure your browser to use this server and port as its proxy
>>>> Browse any page and CTRL-ALT-DblClick on the page to bring up the Sahi Controller
-----
Reading browser types from: /Users/morireo/sahi/userdata/config/browser_types.xml
-----

Sahiプロキシがポート9999で立ち上がります。
この状態で http://localhost:9999/ などどやるとStart URL:という画面になるので、これが出ていれば正常に動作しています。

 

Symfony2でSahiとBehat+minkの設定

test.phonegap.localをVirtualHostの設定でweb/phonegap/に向けます。

behat+minkの設定

app/config/config_test.yml を作ります。

behat: ~

mink:
    base_url:   http://test.phonegap.local/

    sahi:
      host:     %sahi_host%

    browser_name: firefox
    show_cmd:   open %s
    default_session: sahi
    # default_session: symfony
    goutte: ~

FeatureContextを少し書き換える

BehatのFeatureContextを少し書き換えます。extends BehatContextの部分を、MinkContextにします。

namespace Phonegap\TestBundle\Features\Context;

use Behat\BehatBundle\Context\BehatContext,
    Behat\BehatBundle\Context\MinkContext;

use Behat\Behat\Context\ClosuredContextInterface,
    Behat\Behat\Context\TranslatedContextInterface,
    Behat\Behat\Exception\PendingException;

use Behat\Gherkin\Node\PyStringNode,
    Behat\Gherkin\Node\TableNode;

/**
 * Feature context.
 *
 * BehatContext or MinkContext
 */
class FeatureContext extends MinkContext
{
  public function __construct($parameters)
  {
    parent::__construct($parameters);
  }
}

フィーチャの記述

ここからはSymfony2で行います。Symfony2で予めBehatとMinkのバンドルをインストールする必要があります。インストール方法は割愛しますが、https://github.com/reoring/phonegap_bdd_sample に動作するサンプルを置いてあります

下記のようなフィーチャファイルをsrc/Phonegap/TestBundle/Features/phonegap.feature として記述します。

先頭行の# language: ja とすることでフィーチャの記述が日本語で記述できます。

このフィーチャではMinkの組み込みステップを使っています。Appendixに組み込みステップの一覧を記述しています。

# language: ja
フィーチャ: PhoneGapのコンテンツをテスト
  背景:

  シナリオ: トップページからメニューへの遷移
    前提 ユーザーは "/index.html" を表示している
    ならば レスポンスに "コンテンツエリア" が含まれていること
    もし ユーザーが "メニュー" のリンク先へ移動する
    ならば 画面に "メニュー表示" と表示されていること

これを書いたら実行します。

./app/console behat -e=test src/Phonegap/TestBundle/Features/phonegap.feature
フィーチャ: PhoneGapのコンテンツをテスト

  背景: # src/Phonegap/TestBundle/Features/phonegap.feature:3

  シナリオ: トップページからメニューへの遷移                 # src/Phonegap/TestBundle/Features/phonegap.feature:5
    前提 ユーザーは "/index.html" を表示している           # Phonegap\TestBundle\Features\Context\FeatureContext::visit()
    ならば レスポンスに "コンテンツエリア" が含まれていること # Phonegap\TestBundle\Features\Context\FeatureContext::assertResponseContains()
    もし ユーザーが "メニュー" のリンク先へ移動する          # Phonegap\TestBundle\Features\Context\FeatureContext::clickLink()
    ならば 画面に "メニュー表示" と表示されていること        # Phonegap\TestBundle\Features\Context\FeatureContext::assertPageContainsText()

1 scenario (1 passed)
4 steps (4 passed)
0m9.213s

実行するとブラウザが自動的に起動してテストが実行されます。

Appendix.

Minkで使える組み込みステップ


Given /^(?:|ユーザーは )"(?P<page>[^\s]+)" を表示している$/
When /^(?:|ユーザーが )"(?P<page>[^\s]+)" へ移動する$/
When /^(?:|ユーザーが )ページをリロードする$/
When /^(?:|ユーザーが )履歴の前のページに戻る$/
When /^(?:|ユーザーが )履歴の次のページヘ進む$/
When /^(?:|ユーザーが )"(?P<button>(?:[^"]|\\")*)" ボタンをクリックする$/
When /^(?:|ユーザーが )"(?P<link>(?:[^"]|\\")*)" のリンク先へ移動する$/
When /^(?:|ユーザーが )"(?P<field>(?:[^"]|\\")*)" フィールドに "(?P<value>(?:[^"]|\\")*)" と入力する$/
When /^(?:|ユーザーが )"(?P<value>(?:[^"]|\\")*)" という値を "(?P<field>(?:[^"]|\\")*)" に入力する$/
When /^(?:|ユーザーが)次のように入力する:$/
When /^(?:|ユーザーが )"(?P<option>(?:[^"]|\\")*)" という値を "(?P<select>(?:[^"]|\\")*)" から選択する$/
When /^(?:|I )additionally select "(?P<option>(?:[^"]|\\")*)" from "(?P<select>(?:[^"]|\\")*)"$/
When /^(?:|ユーザーが )"(?P<option>(?:[^"]|\\")*)" にチェックをつける$/
When /^(?:|ユーザーが )"(?P<option>(?:[^"]|\\")*)" のチェックをはずす$/
When /^(?:|ユーザーが)パス "(?P<path>[^"]*)" にあるファイルを "(?P<field>(?:[^"]|\\")*)" に添付する$/
Then /^(?:|ユーザーが )(?P<page>[^\s]+) を表示していること$/
Then /^the (?i)url(?-i) should match "(?P<pattern>(?:[^"]|\\")*)"$/
Then /レスポンスコードが (?P&gt;code&lt;\d+) であること/
Then /^the response status code should not be (?P\d+)$/
Then /^(?:|画面に )"(?P<text>(?:[^"]|\\")*)" と表示されていること$/
Then /^(?:|画面に )"(?P<text>(?:[^"]|\\")*)" と表示されていないこと$/
Then /^レスポンスに "(?P<text>(?:[^"]|\\")*)" が含まれていること$/
Then /^レスポンスに "(?P<text>(?:[^"]|\\")*)" が含まれていないこと$/
Then /^"(?P<element>[^"]*)" エレメントに "(?P<text>(?:[^"]|\\")*)" と表示されていること$/
Then /^"(?P<element>[^"]*)" エレメントに "(?P<value>(?:[^"]|\\")*)" という値が含まれていること$/
Then /^(?:|画面に )"(?P<element>[^"]*)" エレメントが表示されていること$/
Then /^(?:|画面に )"(?P<element>[^"]*)" エレメントが表示されていないこと$/
Then /^"(?P<field>(?:[^"]|\\")*)" フィールドに "(?P<value>(?:[^"]|\\")*)" が含まれていること$/
Then /^"(?P<field>(?:[^"]|\\")*)" フィールドに "(?P<value>(?:[^"]|\\")*)" が含まれていないこと$/
Then /^チェックボックス "(?P<checkbox>(?:[^"]|\\")*)" のチェックがついていること$/
Then /^チェックボックス "(?P<checkbox>(?:[^"]|\\")*)" のチェックがはずれていること$/
Then /^(?:|I )should see (?P<num>\d+) "(?P<element>[^"]*)" elements?$/
Then /^最後のレスポンスを表示$/
Then /^最後のレスポンスをブラウザで表示$/

 

ラベル: , , , , ,

JSXをSymfony2のAsseticで自動的にコンパイルする

2012年6月4日月曜日 投稿者 森怜峰 0 コメント

JSXをSymfony2のAsseticで自動コンパイルしてみますよ。

AsseticはAssetにフィルタを適応する仕組みです。今回はJSXのコンパイル処理をAsseticで自動的にコンパイルしてみます。

まずは、JSX本体の準備

git clone http://github.com/jsx/JSX.git

node.jsが入っていなければインストール

brew install node.js

npm(node package manager)が入っていなければインストール

curl http://npmjs.org/install.sh | sudo sh

それか

brew install npm

JSXのソースをコンパイルして実行してみる

cd JSX
./bin/jsx --executable --output hello.js example/hello.jsx
node hello.js
Hello, world!

 

Symfony2側の用意

Symfony2側のAsseticフィルタクラスの追加

JSX用のフィルタクラス追加します。ここに、vendor/assetic/src/Assetic/Filter/JsxFilter.php を下記内容で追加。

namespace Assetic\Filter;

use Assetic\Asset\AssetInterface;
use Assetic\Util\ProcessBuilder;

/**
 * Compiles JSX into Javascript.
 *
 */
class JsxFilter implements FilterInterface
{
  private $jsxPath;

  public function __construct($jsxPath = '/usr/bin/jsx')
  {
    $this->jsxPath = $jsxPath;
  }

  public function filterLoad(AssetInterface $asset)
  {
    $input = tempnam(sys_get_temp_dir(), 'assetic_jsx');
    file_put_contents($input, $asset->getContent());

    $pb = new ProcessBuilder();
    $pb
      ->inheritEnvironmentVariables()
      ->add($this->jsxPath)
      ->add($asset->getSourceRoot() . DIRECTORY_SEPARATOR . $asset->getSourcePath())
    ;

    $proc = $pb->getProcess();

    $code = $proc->run();
    unlink($input);

    if (0 < $code) {
      throw new \RuntimeException($proc->getErrorOutput());
    }


    $asset->setContent(str_replace($asset->getSourceRoot(), "", $proc->getOutput()));
  }

  public function filterDump(AssetInterface $asset)
  {
  }
}

 

次に、DIコンテナの設定をします

/Users/morireo/Sites/fotofoo_mobile/vendor/bundles/Symfony/Bundle/AsseticBundle/Resources/config/filters/jsx.xml ファイルを編集。

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <parameters>
        <parameter key="assetic.filter.jsx.class">Assetic\Filter\JsxFilter</parameter>
        <parameter key="assetic.filter.jsx.bin">/usr/bin/jsx</parameter>
    </parameters>

    <services>
        <service id="assetic.filter.jsx" class="%assetic.filter.jsx.class%">
            <tag name="assetic.filter" alias="jsx" />
            <argument>%assetic.filter.jsx.bin%</argument>
        </service>
    </services>
</container>

app/config/config.ymlにフィルタ設定の記述

assetic:
    filters:
        jsx:
            jsx_path: /usr/bin/jsx

JSXクラスの記述

Resources/public/jsx/hello.jsx などに書きます

import "js/web.jsx";

class _Main {
  static function main(args : string[]) :void {
    log "Hello, world!";
  }

  static function say() : void {
    var text = dom.window.document.createTextNode("Hello, world!");
    dom.getElementById("hello").appendChild(text);
  }
}

Twigに記述

<html>
<head>
  <title></title>
  {% javascripts debug=true output="/js/hello.js" '@JsxTestBundle/Resources/public/jsx/hello.jsx' filter='jsx' %}
  <script src="{{ asset_url }}"></script>
  {% endjavascripts %}
</head>
<body>

<p id="hello"></p>

<script>
  window.addEventListener("load", function(e) {
    JSX.require("/Resources/public/jsx/hello.jsx")._Main.say$();
  });
</script>

</body>
</html>

これで自動的に.jsxファイルが.jsファイルになってブラウザ上で動作するようになりました。

静的ファイルとして配置するには、./app/console assetic:dump コマンドで web/ 以下に配置されます。プロダクション環境では自動的に再生成されないので、ソースファイルを変更した場合には削除するかassetic:dumpで配置してあげる必要があります。

ラベル: , , ,

Macでアプリケーションのショートカットキーを⌘(コマンド)長押しで表示する「CheatSheet」

2012年5月29日火曜日 投稿者 森怜峰 0 コメント

http://www.cheatsheetapp.com/CheatSheet/

CheatSheet をダウンロードして実行する。

ショートカットを調べたいアプリケーションにフォーカスして、⌘を長押しすると…。Fullscreen

この様な感じでショートカット一覧が表示できる。画面はTextMateのもの。

Cocoaアプリケーションでしか反応しないみたい。

ラベル: ,

Mac OS X 10.7で原因不明のフリーズが発生

2012年5月23日水曜日 投稿者 森怜峰 0 コメント

ここのところMac OS X 10.7がちょこちょこフリーズする。
前からたまにはあったがここまで頻発はしてなかったが、最近ひどいので気合を入れて解決してみることにした。 

Console.appで確認すると、IOSurface: buffer allocation size is zero というメッセージが出てフリーズしているみたい。

検索してみると、http://nanofunk.net/mac-osx-lion-10-7-system-freezes-kernel-iosurface-buffer-allocation-size-is-zero-console-message/ この人も同じ症状みたい。

どうやらFlash Playerが悪さをしているようだ。

Flash Playerは標準でアンインストーラが入っていない(!!)ので、http://helpx.adobe.com/flash-player/kb/uninstall-flash-player-mac-os.html ここから uninstall_flash_player_osx.dmg というパッケージを入手する。

アンインストールを実行したら念のため再起動しておく。

これでしばらく使ってみているけど、今のところ同症状は発生していない。

Flash PlayerがOSをフリーズさせることなんてあるんだね、そりゃAppleもiPhoneやiPadにFlash Player入れたくないわけだ…。

こんな話とか、「アドビ、「Flash Player 11.2」リリース--開発者向けに新課金制度も導入へ http://cuaoar.jp/2012/03/flash-player-8.html」

「Flash Player プレミアム機能の発表 http://cuaoar.jp/2012/03/flash-player-8.html」こんなのとかあるし。

ますますHTML5への移行をしたくなる内容をなぜAdobe自らやるのだろう、もしかしてFlashの開発を続けたくないのか?なんてことはないだろうけどね。

どうなってしまうことやら。

Mac OS X, version 10.6 and later: uninstall_flash_player_osx.dmg (238 KB) 

ラベル:

PhpStormで画面が狭い人向けのTips

2012年5月22日火曜日 投稿者 森怜峰 0 コメント

こんな感じで色々表示したいけど狭い場合は ⌘1とかを多用するとすっきり。

⌘1はプロジェクトのトグルなど⌘nに割り当てられているので、View > Tool Windows > の一覧から確認。

狭い

 

ほらすっきり

ひろい

ラベル:

SabelでBDDする

投稿者 森怜峰 0 コメント

Sabel PHP FrameworkでBehatを使ってBDD開発できるようにします。

開発環境はLinuxかMacを対象にしているのでWindowsの人はごめんなさい。

まずはBehatのインストール

pear channel-discover pear.symfony.com
pear channel-discover pear.behat.org
pear install behat/behat

ドキュメントはこちら http://pear.behat.org/

正常にインストールできている場合は behat コマンドが使えます。

% behat

[InvalidArgumentException]                  Context class "FeatureContext" not found                                              

behat [-c|--config="..."] [-p|--profile="..."] [--init] [-f|--format="..."] [--out="..."] [--lang="..."] [--[no-]ansi] [--[no-]time] [--[no-]paths] [--[no-]snippets] [--[no-]snippets-paths] [--[no-]multiline] [--[no-]expand] [--story-syntax] [-d|--definitions="..."] [--name="..."] [--tags="..."] [--cache="..."] [--strict] [--dry-run] [--rerun="..."] [--append-snippets] [features]

 もしくは、Features path "/var/www/html/fotofoo/features" does not exist

この様な表示になる。

// コンソールに色が無いよ!という人はbehat --ansi とやってみて。

FeatureContextが無いよといっているのでFeatureContextを作る。

 

作るといってもinitオプションでコマンドを実行するだけ。

% behat --init

そうするとカレントディレクトリの下にfeatures/が作られる。

もう一度 behat

% behat

No scenarios
No steps
0m0.001s

これで準備完了。

実際にフィーチャを実装してみる

とりあえず、適当にモデルを対象にしたfeatureファイルをfeatures/に作成する。

# language: en
#
# features/sabel_test.feature

Feature: test model
  Scenario: test model
    Given model "Test" must be exists
    When I run "selectOne"
    Then I should get name "sabel"

これでbehatコマンドを実行するとステップの雛形を作成してくれる。

% behat

Feature: test model
Scenario: test model # features/sabel_test.feature:6
Given model "Test" must be exists
When I run "selectOne"
Then I should get name "sabel"
2 scenarios (1 passed, 1 undefined)
5 steps (2 passed, 3 undefined)
0m0.052s
You can implement step definitions for undefined steps with these snippets:
/**
* @Given /^model "([^"]*)" must be exists$/
*/
public function modelMustBeExists($argument1)
{
throw new PendingException();
}
/**
* @When /^I run "([^"]*)"$/
*/
public function iRun($argument1)
{
throw new PendingException();
}
/**
* @Then /^I should get name "([^"]*)"$/
*/
public function iShouldGetName($argument1)
{
throw new PendingException();
}
 

で、この結果を features/bootstrap/SabelModelFeatureContext.php に貼り付ける。

そしてSabelModelFeatureContext.phpを認識させるために、FeatureContext.phpのコンストラクタに追加する。

$this->useContext('sabel_test', new SabelModelFeatureContext($parameters));

 

SabelModelFeatureContextの実装はこんなかんじ。

require_once "init.php";
use Behat\Behat\Context\ClosuredContextInterface,
Behat\Behat\Context\TranslatedContextInterface,
Behat\Behat\Context\BehatContext,
Behat\Behat\Exception\PendingException;
use Behat\Gherkin\Node\PyStringNode,
Behat\Gherkin\Node\TableNode;
/**
* Created by JetBrains PhpStorm.
* User: morireo
* Date: 12/5/22
* Time: 12:24 PM
* To change this template use File | Settings | File Templates.
*/
class SabelModelFeatureContext extends BehatContext
{
private $model;
private $result;
 
 /**
* @Given /^model "([^"]*)" must be exists$/
*/
public function modelMustBeExists($argument1)
{
$this->model = MODEL($argument1);
}
 
 /**
* @When /^I run "([^"]*)"$/
*/
public function iRun($argument1)
{
$this->result = $this->model->$argument1("id", 1);
}
 
 /**
* @Then /^I should get name "([^"]*)"$/
*/
public function iShouldGetName($argument1)
{
if ($this->result !== $argument1) {
return false;
}
}
}

ここでinit.phpをrequireしているが、init.phpは下記のようになる。これをしておかないとSabelの機能が使えないので注意。

# features/bootstrap/init.php
<?php
define("SBL_BATCH", true);
define("RUN_BASE", dirname(__FILE__) . "/../../");
require (RUN_BASE . DIRECTORY_SEPARATOR . "Sabel" . DIRECTORY_SEPARATOR . "Sabel.php");
require (RUN_BASE . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "INIT.php");
require (RUN_BASE . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "environment.php");
if (!defined("ENVIRONMENT")) {
echo "SABEL FATAL ERROR: must define ENVIRONMENT in config/environment.php";
exit;
}
$_SERVER["HTTP_HOST"] = "localhost";
$_SERVER["SERVER_NAME"] = "localhost";
$_SERVER["REQUEST_URI"] = "/";
if (isset($_SERVER["argv"][2])) {
$_SERVER["REQUEST_METHOD"] = strtoupper($_SERVER["argv"][2]);
} else {
$_SERVER["REQUEST_METHOD"] = "GET";
}
if (isset($_SERVER["argv"][1])) {
$parsed = parse_url("http://localhost/" . $_SERVER["argv"][1]);
$_SERVER["REQUEST_URI"] = $parsed["path"];
if (isset($parsed["query"])) {
if ($_SERVER["REQUEST_METHOD"] === "POST") {
parse_str($parsed["query"], $_POST);
} else {
parse_str($parsed["query"], $_GET);
}
}
}
if ((ENVIRONMENT & PRODUCTION) > 0) {
Sabel::init();
Sabel_Bus::create()->run(new Config_Bus());
Sabel::shutdown();
} else {
Sabel_Bus::create()->run(new Config_Bus());
}

 

ひとまずこれでSabelでBDDができるようになる。

日本語でfeatureファイルを記述したい場合は.featureファイルの先頭のlanguageをjaにする。

そうすると、フィーチャ シナリオ 背景 前提 かつ ならば そしてのようなキーワードが日本語で記述できる。ステップも日本語で記述する。

キーワードは  behat --story-syntax --lang ja このコマンドで一覧を教えてもらえる。

# language: ja
[フィーチャ|機能]: Internal operations
In order to stay secret
As a secret organization
We need to be able to erase past agents' memory
背景:
前提 there is agent A
かつ there is agent B
シナリオ: Erasing agent memory
前提 there is agent J
かつ there is agent K
もし I erase agent K's memory
ならば there should be agent J
[しかし|但し|ただし] there should not be agent K
[シナリオアウトライン|シナリオテンプレート|テンプレ|シナリオテンプレ]: Erasing other agents' memory
前提 there is agent <agent1>
かつ there is agent <agent2>
もし I erase agent <agent2>'s memory
ならば there should be agent <agent1>
[しかし|但し|ただし] there should not be agent <agent2>
[例|サンプル]:
| agent1 | agent2 |
| D | M |

フィーチャを全て日本語で記述し顧客でも理解できる内容で記述すれば受け入れテストの自動化ができる。

ラベル: ,

CentOS 5.8はtg3ドライバに問題がある

2012年4月8日日曜日 投稿者 森怜峰 0 コメント

CentOS 5.8のタグVLAN(8021q)がtg3ドライバのバグで正常に動作しない。

yum install kmod-tg3-rhel5u7

として再起動すれば解消する。

かなり致命的だ…。SLにも同様の問題があるかは未調査。

ラベル: