Fest + JRuby + Cucumber で Swing のテストをする - 破

何も破ってない気もするけれど。

Step03 最初のステップ - 画面を見つける

cucumber の詳細についてはググってもらうとして。

step を作成する

test-feature/step_definitions/ticket_viewer_steps.ja.rb

Given /^"([^"]*)" が表示されていること$/ do |window_name|
  case window_name
  when /メイン画面/
    component_name = "MainFrame"
  else
    component_name = window_name
  end
  
  #====================================================================================
  # fest の API - WindowFinder を使って、画面を見つける
  # 変数の前に @ をつけておけば、他のところでも参照できる。(仕組みはイマイチ分からんが)
  #====================================================================================
  @current_window = FestFinder::WindowFinder.findFrame(component_name).using($my_robot)
end

タイトルで検索するメソッドはない(自作すればできる)ので、タイトルを画面名に変換して検索。
WindowFinder.findFrame を呼ぶだけでは画面は見つけられなくって、 using でロボットを指定する必要がある。

画面が見つからない場合、 fest が以下のようなエラーを吐くので、その辺のコードはいらない。

そういえば、ロボットは実行中のテストで唯一のほうがいいと、どっかのページで見たことがあったぞ…。
WindowFinder, ロボットを唯一にするために、 env.rb を修正する。

test-feature/support/env.rb

#=======================================================================================
# Java のライブラリを使えるようにする
#=======================================================================================
include java

#=======================================================================================
# festの名前空間を定義
#=======================================================================================
# クラスパスを通して
Dir["#{File.dirname(__FILE__)}/../../lib/fest\*.jar"].each { |jar| require jar }
# 名前空間を定義する
module FestFeature
  include_package 'org.fest.swing.fixture'
end
module FestFinder
  include_package 'org.fest.swing.finder'
end
module FestCore
  include_package 'org.fest.swing.core'
end

#=======================================================================================
# 製品の名前空間を定義
#=======================================================================================
# こっちも同様に
require "#{File.dirname(__FILE__)}/../../dist/AutomatedUITestingJava.jar"
module MyPrjTicketViewer
  include_package 'local.myproject.ticket_viewer'
end

#=======================================================================================
# このテスト用のロボットを作成する
#=======================================================================================
$my_robot = FestCore::BasicRobot.robotWithNewAwtHierarchy

#=======================================================================================
# 画面を作って、表示する
#=======================================================================================
# Fixture の詳細は http://easytesting.org/swing/apidocs/index.html 辺を参照のこと
main_frame = FestFeature::FrameFixture.new $my_robot, MyPrjTicketViewer::MainFrame.new
main_frame.show

#=======================================================================================
# Cucumber のテストが終わった後にやること
#=======================================================================================
at_exit do
  # fest が使った資源をきれいさっぱり掃除する
  main_frame.cleanUp
end
実行する
> cucumber ..\test-feature --format html --out cucumber.html

無事メイン画面を見つけて、ステップが成功。

整理する

Webアプリのテストとかだと support/paths.rb とかで画面名とURLの対応を取ってる。
それをまねして。

test-feature/support/window_name.rb

def window_name_to(window_title)
  case window_title
  when /メイン画面/
    ret_val = "MainFrame"
  else
    raise "画面名をマッピングできませんでした #{window_title}"
  end
  return ret_val
end

変数名がちょい変わったので、steps 側も修正。

Step04 テキストボックスに値を入力する

次のステップ。さっきと同じように step_definitions/ticket_viewer_steps_ja.rb にコードを追加すればOK。
fest の FrameFixture クラスにある textBox メソッドにコントロールの名前を渡せばOK

test-feature/step_definitions/ticket_viewer_steps_ja.rb

When /^"([^"]*)" に "([^"]*)" を入力する$/ do |name, value|
  case name
  when /URL/
    control_name = "ctlURL"
  else
    raise "コントロール名をマッピングできませんでした #{name}"
  end

  #====================================================================================
  # textbox に値を入力する場合は setText を使う (enterText だと http:// が http+// になってしまった…)
  #====================================================================================
  @current_window.textBox(control_name).setText(value)
end
実行する

おや? http:// じゃなくって http+// になるぞ?
setText にすると http:// になるな。なぜだ…。気持ち悪いけど setText でいくことにする。

整理する

やっぱり control_name.rb があったほうがいいかなぁ。

test-feature/support/control_name.rb

詳細は略。

Step05 ボタンをクリックする

同じように FrameFixture の button メソッドでボタンを見つけて、click メソッドを呼べばいい。

test-feature/step_definitions/ticket_viewer_steps_ja.rb

When /^"([^"]*)" ボタンをクリックする$/ do |name|
  control_name = control_name_to(name)
  
  #====================================================================================
  # click でボタンをクリック。説明なんていらないよな。
  #====================================================================================
  @current_window.button(control_name).click
end

コントロール名への変換は control_name.rb で。

実行する

押してるっぽい。ポーズとかできると良いんだけども…。

Step06 値を検査する

テキストで書いた表を使って値の検査ができるのは、 cucumber ならでは。
同じように step_definitions/ticket_viewer_steps_ja.rb に追記する。

test-feature/step_definitions/ticket_viewer_steps_ja.rb

Then /^リスト "([^"]*)" に以下が表示されていること:$/ do |name, table|
  control_name = control_name_to(name)
  
  #====================================================================================
  # FrameFixture.list で JList を見つける。
  # contens メソッドはリストの内容を String の配列にしてくれる。
  # Cucumber::Ast::Table の diff! を使えるよう、[["hoge"],["fuga"]] のように配列の配列にする
  # 多分もっと良い方法があるに違いない。
  #====================================================================================
  list = @current_window.list(control_name).contents.map {|project_name|[project_name]}

  #====================================================================================
  # Cucumber::Ast::Table の diff! を使って簡単に内容を比較できる(こりゃ楽だ)
  #====================================================================================
  table.diff!(list)
end

ここはちょっとだけ説明。上記のように書いておくと、

    ならば リスト "プロジェクト一覧" に以下が表示されていること:
      |r-labs        |
      |Hudson        |
      |IssueExtension|
      |WikiExtension |

の内容を見て name に "プロジェクト一覧" が、 table に表の部分が読み込まれる。
table の正体 Cucumber::Ast::Table クラス。

このクラス、 diff! メソッドで内容を比較してくれる。便利!
評価したい内容を 配列の配列、または ハッシュの形にして、 diff! メソッドに渡せば良い。

table の内容と違っていると...

のように違ってる場所を示してくれる。さらに便利!

Fest + JRuby + Cucumber で Swing のテストをする - 序

本人が行き当たり場当たりな性格なので、予告なく内容が変わることがあります(特にコード)

動機

  • Swing のテストをやることになった
  • どうせなら自動化
  • Cucumber 使えないかな
    • JRuby を使えばいけるかな?
    • UI はどうやって叩くんだろう
      • Cucumber + Swinger でできるらしい
      • Swinger 機能がちょっと少ない?
      • 他にないかな
      • Fest ってのがあるらしいぞ
  • Fest + JRuby + Cucumber + Ant でCIだ

材料

インストール

JDK/Juby/Ant インストール

適当で。

Cucumber インストール
> jgem install cucumber
Fest インストール
  • fest-assert-1.4.jar
  • fest-mocks-1.0.jar
  • fest-swing-1.2.jar
  • fest-util-1.1.2.jar
  • fest-util-1.1.2.jar

を適当なディレクトリに置く。

Step01 - 最初の一歩

ディレクトリを掘る
automated-ui-testing-java
  + src
      + local
         + myproject
             + ticket_viewer
  + test-feature
      + step_definitions
      + support
テストコードを書く
# language: ja
フィーチャ: チケット画面を出すところまで
  シナリオ: No1. プロジェクト一覧を取得する
    前提   "メイン画面" が表示されていること
    もし   "URL" に "http://www.r-labs.org/projects.xml" を入力する
    かつ   "ctlFetchProjectList" ボタンをクリックする
    ならば "プロジェクト一覧" に以下が表示されていること:
      |r-labs        |
      |Hudson        |
      |IssueExtension|
      |WikiExtension |
おもむろにテストを実行する

Windowsのコンソールに出すと文字化けするので、仕方なく HTML に出力する
結果は cucumber.html に出力される。

> cucumber test-feature --format html -out cucumber.html
> cucumber.html

当然のごとくテストは動かないので、ここからイロイロやるわけですな。

Step02 - まずは画面を表示する

製品コードを書く

メイン画面とチケット一覧画面を作る。
適当にコントロールとボタンを配置する。

automated-ui-testing-java
  + src
      + local
         + myproject
             + ticket_viewer
                 + MainFrame.java
                 + TicketListFrame.java 
fest を使って画面を表示する

fest FrameFixture を作って画面を表示する。
別にここでテストするわけじゃないので、単に Frame を setVisible すればイイだけではあるが。

テストシナリオの中で起動しても良いんだけども、at_exit フックを使いたかったので
テストシナリオの前に画面を表示する方向で。
support/env.rb に書けば、事前に実行してくれるんじゃないかな?

support/env.rb

#=======================================================================================
# Java のライブラリを使えるようにする
#=======================================================================================
include java

#=======================================================================================
# festの名前空間を定義
#=======================================================================================
# クラスパスを通して
Dir["#{File.dirname(__FILE__)}/../../lib/fest\*.jar"].each { |jar| require jar }
# 名前空間を定義する
module FestFeature
  include_package 'org.fest.swing.fixture'
end

#=======================================================================================
# 製品の名前空間を定義
#=======================================================================================
# こっちも同様に
require "#{File.dirname(__FILE__)}/../../dist/AutomatedUITestingJava.jar"
module MyPrjTicketViewer
  include_package 'local.myproject.ticket_viewer'
end

#=======================================================================================
# 画面を作って、表示する
#=======================================================================================
# Fixture の詳細は http://easytesting.org/swing/apidocs/index.html 辺を参照のこと
mainFrame = FestFeature::FrameFixture.new MyPrjTicketViewer::MainFrame.new
mainFrame.show

#=======================================================================================
# Cucumber のテストが終わった後にやること
#=======================================================================================
at_exit do
  # fest が使った資源をきれいさっぱり掃除する
  mainFrame.cleanUp
end
実行する

画面が一瞬表示されて、終了したらOK。
何もしてないので、当然テストは成功しない。

Cobertura に日本語パッチを当てる 1.9.4.1 版

タイトルは coberturaに日本語パッチをあてる - お仕事の備忘録みたいなもの からいただきました。どもすみません。

※ cobertura のテストが幾つか失敗してます。参考程度にどうぞ。
Cobertura が用意しているテストはクリアしたので、まぁまぁ大丈夫だと思います。が、動作の保証まではできません。ごめんなさい。

  • UTF-8 で "(" を含んだ文字列

が入っていると、ant の cobertura-report タスクで以下のようなエラーを吐いて死ぬ。超困る。何とかせねば。

TokenMgrError: Lexical error at line 17, column 38.  Encountered: "\r" (13), after : "\"\u8b41\uff70\u7e3a\u52b1\uff1e\ufffd\ufffd.equals(arg) ) {"
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParserTokenManager.getNextToken(JavaParserTokenManager.java:2078)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.jj_scan_token(JavaParser.java:10181)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.jj_3R_198(JavaParser.java:8524)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.jj_3R_178(JavaParser.java:8924)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.jj_3R_151(JavaParser.java:8901)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.jj_3R_102(JavaParser.java:8960)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.jj_3_25(JavaParser.java:9977)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.jj_2_25(JavaParser.java:5999)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.Expression(JavaParser.java:2762)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.IfStatement(JavaParser.java:4251)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.Statement(JavaParser.java:3816)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.BlockStatement(JavaParser.java:3997)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.Block(JavaParser.java:3947)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.MethodDeclaration(JavaParser.java:2039)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.ClassBodyDeclaration(JavaParser.java:1082)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.ClassBody(JavaParser.java:941)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.UnmodifiedClassDeclaration(JavaParser.java:854)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.ClassDeclaration(JavaParser.java:761)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.TypeDeclaration(JavaParser.java:608)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.CompilationUnit(JavaParser.java:353)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.parser.JavaParser.parse(JavaParser.java:137)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.Javancss._measureSource(Javancss.java:256)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.Javancss._measureRoot(Javancss.java:339)
[cobertura-report] 	at net.sourceforge.cobertura.javancss.Javancss.<init>(Javancss.java:419)
[cobertura-report] 	at net.sourceforge.cobertura.reporting.ComplexityCalculator.getAccumlatedCCNForSource(ComplexityCalculator.java:104)
[cobertura-report] 	at net.sourceforge.cobertura.reporting.ComplexityCalculator.getAccumlatedCCNForSingleFile(ComplexityCalculator.java:141)
[cobertura-report] 	at net.sourceforge.cobertura.reporting.ComplexityCalculator.getCCNForSourceFileNameInternal(ComplexityCalculator.java:226)
[cobertura-report] 	at net.sourceforge.cobertura.reporting.ComplexityCalculator.getCCNForPackageInternal(ComplexityCalculator.java:196)
[cobertura-report] 	at net.sourceforge.cobertura.reporting.ComplexityCalculator.getCCNForProject(ComplexityCalculator.java:166)
[cobertura-report] 	at net.sourceforge.cobertura.reporting.html.HTMLReport.generateTableRowForTotal(HTMLReport.java:704)
[cobertura-report] 	at net.sourceforge.cobertura.reporting.html.HTMLReport.generateOverview(HTMLReport.java:336)
[cobertura-report] 	at net.sourceforge.cobertura.reporting.html.HTMLReport.generateOverviews(HTMLReport.java:271)
[cobertura-report] 	at net.sourceforge.cobertura.reporting.html.HTMLReport.<init>(HTMLReport.java:96)
[cobertura-report] 	at net.sourceforge.cobertura.reporting.Main.parseArguments(Main.java:107)
[cobertura-report] 	at net.sourceforge.cobertura.reporting.Main.main(Main.java:176)
[cobertura-report] WARN   getAccumlatedCCNForSource, JavaNCSS got an error while parsing the java file D:\Development\_Projects\cobertura-test\.\src\local\my\project\HelloWorld.java
[cobertura-report] TokenMgrError in STDIN
[cobertura-report] Lexical error at line 17, column 38.  Encountered: "\r" (13), after : "\"\u8b41\uff70\u7e3a\u52b1\uff1e\ufffd\ufffd.equals(arg) ) {"

調査

Cobertura をビルドできるようにする
> ant jar

で JAR作成してくれる。

やばそうなところを見つける

スタックトレースから追いかけるだけの簡単なお仕事。
最初は net.sourceforge.cobertura.javancss.parser.JavaParserTokenManager.getNextToken
辺りを見ていたんだけど、さっぱり分からないので、呼び出し元を見ながら分かりそうなところまで行ってみる。

で、分かったこと。

            private Complexity getAccumlatedCCNForSource(String sourceFileName,
                    Source source) {
                if (source == null) {
                    return ZERO_COMPLEXITY;
                }
                if (!sourceFileName.endsWith(".java")) {
                    return ZERO_COMPLEXITY;
                }
                Javancss javancss = new Javancss(source.getInputStream()); /* ここだ! */

コードを修正する

Ant の cobertura-report タスクにある encoding プロパティ?を使えるように修正してみる。

net.sourceforge.cobertura.reporting.Main.java
103:   ComplexityCalculator complexity = new ComplexityCalculator(finder);
104:    complexity.setEncoding(encoding);
net.sourceforge.cobertura.reporting.ComplexityCalculator
 67:    private Map packageCNNCache = new HashMap();
 68:    
 69:    private String encoding;
 95:    private Complexity getAccumlatedCCNForSource(String sourceFileName, Source source) {
 96:    if (source == null)
 97:    {
 98:        return ZERO_COMPLEXITY;
 99:    }
100:    if (!sourceFileName.endsWith(".java"))
101:    {
102:        return ZERO_COMPLEXITY;
103:    }
104:    Javancss javancss = new Javancss(source.getInputStream(), encoding);
245:    public void setEncoding(String encoding) {
246:        this.encoding = encoding;
247:    }
net.sourceforge.cobertura.javancss.Javancss
413:    public Javancss(InputStream isJavaSource_, String encoding) {
414:        Util.debug( "Javancss.(InputStream).sJavaSourceFile_: " + isJavaSource_ );
415:        _sErrorMessage = null;
416:        _vJavaSourceFiles = null;
417:        this.encoding = encoding;

ビルドして実験

無事カバレッジが作成された!!
気の迷いかもしれないので、ソースを元に戻して再度挑戦。大丈夫そう。

テストを通す

せっかく作ってくれているテストは通しておきたい…。

> ant

net.sourceforge.cobertura.test.SwitchFunctionalTest のテストが1つこけるけども、これは修正前もこけてたのでよしとする。

Agile2011 でやってみること

きいてみる

やってる人に聞いてみたいことをまとめてみる。
でも、この質問、英語にしなきゃいけないし、回答も英語なんだよな…。

  • スクラムやってる?
  • Done の定義 Story/Sprint/Release のように分けて決めてる?
    • Story と Sprint 分けてる理由って?
    • Sprint の Done が達成できなかったらどうしてる?
  • ScrumAlliance の Doneの定義書いた人に決めた経緯とか聞きたい
    • あれをベースにこれって何故こうしてるんだと思う?って話をしてみたい
    • 英語力ないとまず無理だな…orz
  • スプリント0 で何してる? 期間はどのくらい?
    • なぜそうしたの?
  • P.O. は受け入れテストどうしてる?
    • 自動化はやっぱりチームが手伝ってる?
  • ドキュメントどれくらい書いてる?
    • ReleaseSprint でドキュメント清書したりしてる?
    • 清書するとしたら、Sprint でどれくらい書いてる?
  • P.O. はどうやって要件を管理してるの?
    • 全てを PBL で管理してる? それとも製品の要件は別文書として管理してる?

最終的には自分で決めなきゃいけないことは分かってるんだけど
やっぱり聞いてみたいのよね。

OpenJam でカンバンでも作って座ってたら、あっちから来てくれるかな?
そしたら話しかける勇気なくても大丈夫…。

  • @sandayuu さんのオブ脳セッションに参加する(手伝いできればいいけど)
  • AgileSamurai を買ってたら作者さんにお礼をいう(今やっていることのヒントになるはずだから)

AgileScout - 大規模開発にアジャイルを適用する際の10のTIPS

10 Tips for Agile Adoption in the Enterprise | Agile Scout より。

英語力は地を這っている人なので、中身についてはあまり信用しないように。

1. マネジメント層を取り込め

彼らを引き込まないと、ウォーターフォール向きのレポートに変換する作業がついて回る。

2. 全リリースの計画をしろ、1スプリントだけじゃない

ストーリーポイントで見積もり、ベロシティを予測し、スプリント計画を立てよう。
でも、最初に立てた計画にガチガチに縛られないよう注意。

3. スプリントを計画しろ、特別、共有なリソースのことを念頭において

遠い未来の計画に縛られる必要はないけれど、計画は立てよう。

4. 複雑な内部の依存関係は現実に起こる、それに対処せよ

リリース計画でモジュールやコンポーネントの依存関係を特定しておこう。スプリントゼロってやつ。
スプリントゼロでは全般的なアーキテクチャの要件?を設計しておく。スプリントのオーバーヘッドとならないように。

5. 妥当なスプリントの長さを継続せよ、3〜4週間

本格的なシステム統合をするには2週間では短い。
3〜4週間の長さを継続する。完全なサービスか、統合を開発し、テストできるように。

6. すべてのスプリントの成果物が製品になるとは思うな

初期のスプリントではEnd-to-Endでのシステム統合を準備することになる。

7. DONEを定義せよ、全てのチームにおいて首尾一貫しているDONEだ

8. 少なくとも2スプリントを安定化のために用意せよ

バグ出しや、システムテスト、デプロイのためのタスクの片付けとか。

9. 使い物になるドキュメントを作れ

大量のドキュメントの代わりに、Agile Document Templete や Wiki を使え。
Agile Documente Template って何?
コメントだけで大丈夫とか言って、ドキュメントをさぼらないように。

10. 継続的インテグレーションの原則を導入せよ

言うまでもなし。


コメントも結構ある。でも訳すの大変だからやらない。

AgileJapan2011 まとめ

対会社向け。
SlideShare の検索はほとんど見つからない。GW 前には集まるといいな。
増えてきた!

東京

アジャイル開発の適切な運用に向けて

IPAウォーターフォール型開発WGの成果発表。大御所から出てくる資料は会社の上層部に効いたりする。

Agile Japan 2011 - Linda Rising さんの基調講演の録画 - kawaguti の日記 (id:wayaguchi)

川口さんの。なんと動画。ふとっぱらだ!

スライドもある。至れり尽くせり。

立ち上がれ、義理・人情プログラマ

基幹システムをシェルスクリプトとテキストファイルでくみ上げた超人 當仲さんのプレゼン。
ITで信頼社会を取り戻せ!という台詞は非常に熱くなった。
信頼駆動のアジャイル開発はその一翼を担うことができるはず。

アジャイルコンサルタントの秘密

いったいいくつ秘密があるのか良く分からない牛尾さんのスライド。

AgileJapan2011ふりかえりセッション

ダイアログファシリテーター 高柳さんのふりかえりセッション。
実は参加できなかった…。

北海道

Agile is degree

北海道。角谷さんのスライド。が上手くアップロードできないらしく、PDF。

トラスティア 事例紹介

カンバンの歴史が。こういう風に成長していく様が見えるのって良い。

仙台

アジャイル開発が上手くなるための4つのステップ

Scrum道 のプロダクトオーナー nawoto さんのスライド。SlideShare のが変なので。
うーん。何故か iframe が使えない。ここだけ。

富山

その一方で、ウォーターフォールの現場にて開発者が出来ること

これぞ SmallSuccess StepByStep だ!

愛媛

愛媛サテライト オープニング

ライトニング・トークスをリレーでやったんだ! すげぇ。

Agile Japan 愛媛サテライト」に参加しました - charonbyの日記

参加した人の感想。午後のワークショップ面白かったみたい。

未分類

Agile japan2011 amano

これは何だろう?

Team Foundation Server で遊ぼう (1)

VirtualPC + WindowServer2008 + TeamFoundationServer で遊んでみる。

2010/11/03時点の情報です。

VirtualPC のスペック

メモリ:1.5GB
HDD:13GB * 2

@tomohn さんによると、メモリは評価/デモなら 1G あれば十分らしい。
VirtualPC では1つのHDDの制限が 13G 。
結構容量食いそうな気がするので、ドライブは2つ用意しておく。

ダウンロード

Window Server 2008 評価版

http://www.microsoft.com/japan/windowsserver2008/trial-software.mspx から。
アカウントが必要ですよ。

Team Foundation Server 2010 評価版をダウンロードする

http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=3660cacf-f077-44d3-a9d9-97e801da2035
こっちはアカウント要りません。

インストール

Windows Server 2008

Enterprise にひかれるけど、 Standard エディションでガマン。
インストールは30分くらいで終了。とっても簡単。
WindowsUpdate かけたら、66個の更新が………。

最後のほうにIE8のインストールがあって、ボタンのクリックなどが必要になるからお気をつけて。

Window Server 2008 SP2

http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=a4dd31d5-f907-4406-9012-a5c3199ea2b3

アップデートしようとしたら失敗。システム更新準備ツール を適用してみる。

http://www.microsoft.com/downloads/details.aspx?familyid=0435684B-8D12-4028-9CB0-B2903257F1FD&displaylang=ja

意外と時間かかる。どうやら成功。
SP2のインストールは1時間くらいかかるそうだ。

Team Foundation Server 2010

イメージをマウント。
TFS-x86 にある setup を起動。
必要なコンポーネントは全て自動でインストールしてくれるっぽい。楽すぎて怖い。

TFSの構成

インストールが終わると、構成ウィザードが出てくる。

標準構成でシステムをチェック。片っ端からエラー。
再起動が必要らしい。

[Team Foundation Server 管理コンソール] -> [アプリケーション層] -> [インストール済みフィーチャーの構成] で
再度設定ができる。

再度チャレンジ。以下のエラーが。(警告は無視する)

  • 次のSQLSERVERインスタンスに接続できません
  • Analysis Service オブジェクトモデルをウェアハウス処理で仕様できるようにするには…云々。

また明日にする。