42
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~ Microsft MVP for Windows Azure 割と普通 1

基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

Embed Size (px)

DESCRIPTION

CLR/H 69回目勉強会でお話しさせて頂いた、ASP.NET MVC での TDD 基礎見直しです。あじゅらーもASP.NET MVC な人も是非ご一読あれ

Citation preview

Page 1: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

基礎から見直す ASP.NET MVC の単体テスト自動化方法

~ Windows Azure 関連もあるかも~

Microsft MVP for Windows Azure

割と普通

1

Page 2: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

自己紹介

• 割と普通 ( @normalian )

– Windows Azure のコミュニティメンバ

• Japan Windows Azure User Group http://r.jazug.jp/

– わんくま同盟 のコミュニティメンバ

• http://www.wankuma.com/

– Microsoft MVP for Windows Azure 2010~

2

Page 3: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

本セッションの目的とゴール

• 目的

– C#/VB.NET で単体テスト自動化するため、どのようにテストコードを記述すれば良いかを認知

– 単体テスト自動化を支援するツール、ライブラリ群を認知

• ゴール

– C#/VB.NET で、単体テストの自動化が可能なテストコードを効率的に記述することができる

3

Page 4: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

アジェンダ

何故 単体テスト自動化 が必要?

単体テスト自動化 のコツ

単体テストを効率化するツール群

まとめ

参考

Page 5: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

何で単体テスト自動化が必要?

• 良く言われるのは以下のメリット

– 単体テストの工数を削減できる

– コードの保守・再利用性が向上する

– コードが綺麗になる

5

Page 6: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

単体テストの工数を削減できる

6

仕様変更が増える程、単体テスト工数は増大

Page 7: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

コードの保守・再利用性が向上する

• 変更に伴うデグレを瞬時に検知できる

– リファクタリングや保守が容易

– 単体テストコードの動作検証がいつでも可能

• 外部仕様が容易に理解できる

– メソッドの外部仕様がテストコードに記載

– ドキュメント・コードの二重化を防止

7

Page 8: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

コードが綺麗になる

• ソースコードのテスタビリティが向上する

– 単体テストの自動化を意識したインターフェースの定義を強制

– テストコードをマニュアルとして利用可能

– コーディング力が向上

• 若手、新人の教育向けに適用できる

8

Page 9: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

アジェンダ

何故 単体テスト自動化 が必要?

単体テスト自動化 のコツ

単体テストを効率化するツール群

まとめ

参考

Page 10: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

単体テストの対象を明確化する

• データの入出力ポイントに対して単体テストを実施する

コントローラ

画面

モデル

Java

Script

HTML/

CSS モデル

JavaScript で記述したロジックのテスト

JavaScript から C# へのマッピング

モデルのテスト

10 C#

JavaScript

コントローラのテスト

Page 11: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

単体テスト自動化が容易なインターフェースを定義する 1/3

• 従来の ASP.NET Web Forms では、単体テストの自動化がきわめて困難

メインコード

テストコード

Page 12: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

単体テスト自動化が容易なインターフェースを定義する 2/3

• ASP.NET MVC で単体テストの自動化が容易に

メインコード

テストコード

Page 13: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

単体テスト自動化が容易なインターフェースを定義する 3/3

• Testing Framework や NUnit 等で自動テスト可能な外部インターフェース設計とする

13

コントローラ • ViewBag

• Model

ViewReult

Web API の応答

XXXXResult (その他の応答)

Page 14: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

変数名の命名規則に留意する 1/2

• テストメソッド名、変数名からチェック対象を理解できるように命名する

14

[TestMethod]

public void Indexがリストを返す()

{

List<string> expect = new List<string>(){ "a", "b", "c" };

List<string> actual = null;

HomeController controller = new HomeController();

actual = (controller.Index() as ViewResult).Model;

Assert.Equals( expect, actual );

}

良い例

Page 15: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

変数名の命名規則に留意する 2/2

• 「悪い例」では、テストメソッド名、変数名からチェック対象が理解できない

15

[TestMethod]

public void Index ()

{

HomeController controller = new HomeController();

var actual = (controller.Index() as ViewResult).Model;

Assert.Equals(new List<string>(){ "a", "b", "c" }, actual );

}

悪い例

Page 16: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

1メソッド・1アサートを心がける 1/2

• テスト対象を明確化するため、1メソッド・1アサートを心がける

• if 文, for 文, while 文に Assert はダメ、絶対

16

string expect = XXXXXX;

string actual = null;

(中間ロジック)

Assert.Eqauls( expect, actual );

良い例

Page 17: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

1メソッド・1アサートを心がける 2/2

• 「悪い例」では、チェックする場所が散って何をチェックしているか分からない

17

string expect = XXXXXX;

string actual = null;

(中間ロジック)

if(flag == true) {

Assert.Eqauls( expect, actual );

}else{

Assert.Fail(“ここは通らないはず”);

}

悪い例

Page 18: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

モックを効率的に作成する 1/2

• Moq.dll 等を利用して HttpContextBase, IPrincipal, IIdentity 等のモック作成が難しいクラスを作成する

18

[TestMethod()]

public void IndexTest01()

{

string expect = typeof(RedirectToRouteResult).FullName;

string actual;

BuyHistoryController target = new BuyHistoryController(new TestOrderRepository());

//モックの作成

var mockHttpContextBase = new Mock<HttpContextBase>();

var mockIdentity = new Mock<IIdentity>();

var mockPrincipal = new Mock<IPrincipal>();

//ユーザ情報の設定&httpContextオブジェクトの作成

mockIdentity.Setup(identity => identity.IsAuthenticated).Returns(true);

mockIdentity.Setup(identity => identity.Name).Returns("someUser");

mockPrincipal.Setup(principal => principal.Identity).Returns(mockIdentity.Object);

mockHttpContextBase.Setup(httpContextBase => httpContextBase.User)

.Returns(mockPrincipal.Object);

ControllerContext context = new ControllerContext(mockHttpContextBase.Object, new RouteData(), target);

target.ControllerContext = context;

actual = target.Index().GetType().FullName;

Assert.AreEqual(expect, actual);

}

• Moq.dll を利用してもステップ数が多い

• Moq.dll を利用しないと数倍のコード行数になる

Page 19: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

モックを効率的に作成する 2/2

• モック作成は行数が伸びるので共通化する

19

[TestMethod()]

public void IndexTest01(){

string expected= typeof(RedirectToRouteResult).FullName;

string actual;

BuyHistoryController target =

new BuyHistoryController(new TestOrderRepository());

ControllerContext context = new ControllerContext(

Utils.CreateControllerContext(true, "someuser")

, new RouteData(), target);

target.ControllerContext = context;

actual = target.Index().GetType().FullName;

Assert.AreEqual(expect, actual);

}

モック作成を共通化

Page 20: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

名前空間、クラス名の命名規則に留意する

• テスト対象のプロジェクト、クラスが分かりやすいように命名規則を規定する

– プロジェクト名:MyMVC → MyMVC.Test

– クラス名: MyClass → MyClassTest

– メソッド名: MyMethod → MyMethodTest

• 命名規約に従うことで、 TestDriven.NET を利用した、メインコード/テストコードの切り替えが可能

– http://www.testdriven.net/quickstart.aspx

20

Page 21: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

アジェンダ

何故 単体テスト自動化 が必要?

単体テスト自動化 のコツ

単体テストを効率化するツール群

まとめ

参考

Page 22: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

ツールを利用したテスト効率化したい

• 紹介したツール・ライブラリを利用してテストを自動化する

コントローラ

画面

モデル

Java

Script

HTML/

CSS モデル

22 C#

JavaScript

Page 23: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

ツールを利用したテスト効率化(β)

• 紹介したツール・ライブラリを利用してテストを自動化する

コントローラ

View

Model

View

Model

HTML/

CSS モデル

C#

JavaScript

knocko

ut.map

ping.js

knock

out.js

AutoM

apper

Entity

Frame

work

23

Page 24: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

ツールを利用したテスト効率化(β)

• 紹介したツール・ライブラリを利用してテストを自動化する

コントローラ

View

Model

View

Model

HTML/

CSS モデル

knocko

ut.map

ping.js

knock

out.js

AutoM

apper

Entity

Frame

work

QUnit-tap で単体テスト自動化

node.exe

Testing Framework

単体テスト自動化 MSTest.exe

24 C#

JavaScript

Page 25: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

紹介するツール・ライブラリ群

• 今回は以下のライブラリ・ツールを紹介

– knockout.js

– knockout.mapping.js

– AutoMapper

– Qunit-tap

Page 26: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

knockout.js

• DOM 要素と JSON オブジェクトのマッピング機能

26

var viewModel = {

left: ko.observable( 30 ),

right: ko.observable( 40 )

}; viewModel.answer = ko.dependentObservable(function () { return parseInt(this.left()) + parseInt(this.right()); }, viewModel);

ko.applyBindings(viewModel);

<input type=“text” data-bind=“value: left” /> + <input type=“text” data-bind=“value: right” /> = <span data-bind="text: answer"></span>

onblur 等のイベントが発生したタイミングで、ViewModel と

DOM要素で値を同期

Page 27: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

<script type="text/javascript"> //JSONオブジェクトから、ViewModel を作成 var initialData = @Html.Raw(Json.Encode(Model)); var viewModel = ko.mapping.fromJS(initialData); //DOM要素を読み込み後、ViewModel を Binding $( function(){ ko.applyBindings(viewModel); }); </script>

• C#/VB.NET の ViewModel と JSON オブジェクト をマッピング

27

{ name: “若人”, age: 20}

等のJSONに置換される処理

DOM 要素 と viewModel インスタンスとを双方向バインド

Knockout.mapping.js 1/2

Page 28: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

28

$.ajax({ type:“POST”, dataType: "json", contentType: "application/json", data : ko.mapping.toJSON(viewModel), url: "@Url.Content("~/api/Values/")", success : function(res){ alert(JSON.stringify(res)); } });

public class ValuesController : ApiController{ public string Post(ViewModel viewModel){

return "server recieved answer = " + viewModel.answer; }

Knockout.mapping.js 2/2

• C#/VB.NET の ViewModel と JSON オブジェクト をマッピング

Page 29: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

AutoMapper

• Model – ViewModel といったモデル間のマッピングを実施する

• 複数モデルからの集約化等、細かな制御が可能

ViewModel Model

項目1

項目2

Page 30: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

AutoMapper

• 「XXX.ID = YYY.ID」の羅列を防止できる

• マッピングが存在しない場合は一括でチェック可能

Product product = ProductRepository.GetById(id); Mapping.AutoMapperBootstrapper.Configure(); Mapper.CreateMap<Product, ProductViewModel>(); Mapper.Map<Product, ProductViewModel>(product); var productViewModel = Mapper.Map<Product, ProductViewModel>(product);

Page 31: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

QUnit-tap の利用

• node.exe から実行可能な QUnit

– node.exe → Node.js の Windows 実装

– QUnit → ブラウザ上で JavaScript を単体テスト

• knockout.js の ViewModel が対象?

require('../test_helper.js'); QUnit.test('my calc test', function() { var expect = 3; var actual = calc( 1, 2 ); assert.equal(expect, actual); }); QUnit.start();

Page 32: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

アジェンダ

何故 単体テスト自動化 が必要?

単体テスト自動化 のコツ

単体テストを効率化するツール群

まとめ

参考

Page 33: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

まとめ

• ASP.NET MVC は単体テストの自動化に向いている

• 単体テストの自動化を実施するためにはコツがある

• 単体テストの自動化を支援するツールは多々存在する

Page 34: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

View と コントローラの構成 (β)

ViewM

odel View

Model

HTML/CSS Contr

oller

ViewM

odel View

Model

HTML/CSS

ViewM

odel View

Model

HTML/CSS

Model

Model

knockout.map

ping.js knockout.js

C#

JavaScript

1対1 対応 1対N

対応

N対M

対応

対応関係

Entity

Framework

knockout.js

knockout.js

knockout.map

ping.js

knockout.map

ping.js

Entity

Framework

Page 35: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

アジェンダ

何故 単体テスト自動化 が必要?

単体テスト自動化 のコツ

単体テストを効率化するツール群

まとめ

参考

Page 38: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

余談!

Page 39: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

というか

続編!

Page 40: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

クラウド上で単体テスト自動化

• Trac Lightning on Windows Azure – https://github.com/normalian/WATracLightning

Page 41: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

テスト自動化もクラウドへ…

単体テスト自動化

(手動キック)

単体テストの自動化

(自動キック)

全てクラウドへ・・・

Page 42: 基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~

この

はてしなく遠い

自動テスト坂をよ・・・

オレは

ようやく

のぼりはじめた

ばかりだからな

未完