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

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

on

  • 8,816 views

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

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

Statistics

Views

Total Views
8,816
Views on SlideShare
7,285
Embed Views
1,531

Actions

Likes
5
Downloads
24
Comments
0

8 Embeds 1,531

http://d.hatena.ne.jp 1481
http://normalian.hatenablog.com 27
https://twitter.com 10
http://webcache.googleusercontent.com 8
https://twimg0-a.akamaihd.net 2
https://si0.twimg.com 1
http://hatena-anohito.appspot.com 1
http://cache.yahoofs.jp 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

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

    • 基礎から見直す ASP.NET MVC の単体テスト自動化方法~ Windows Azure 関連もあるかも~ Microsft MVP for Windows Azure 割と普通 1
    • 自己紹介• 割と普通 ( @normalian ) – Windows Azure のコミュニティメンバ • Japan Windows Azure User Group http://r.jazug.jp/ – わんくま同盟 のコミュニティメンバ • http://www.wankuma.com/ – Microsoft MVP for Windows Azure 2010~ 2
    • 本セッションの目的とゴール• 目的 – C#/VB.NET で単体テスト自動化するため、どのよ うにテストコードを記述すれば良いかを認知 – 単体テスト自動化を支援するツール、ライブラリ群を 認知• ゴール – C#/VB.NET で、単体テストの自動化が可能なテ ストコードを効率的に記述することができる 3
    • アジェンダ 何故 単体テスト自動化 が必要? 単体テスト自動化 のコツ 単体テストを効率化するツール群 まとめ 参考
    • 何で単体テスト自動化が必要?• 良く言われるのは以下のメリット – 単体テストの工数を削減できる – コードの保守・再利用性が向上する – コードが綺麗になる 5
    • 単体テストの工数を削減できる仕様変更が増える程、単体 テスト工数は増大 6
    • コードの保守・再利用性が向上する• 変更に伴うデグレを瞬時に検知できる – リファクタリングや保守が容易 – 単体テストコードの動作検証がいつでも可能• 外部仕様が容易に理解できる – メソッドの外部仕様がテストコードに記載 – ドキュメント・コードの二重化を防止 7
    • コードが綺麗になる• ソースコードのテスタビリティが向上する – 単体テストの自動化を意識したインターフェースの定 義を強制 – テストコードをマニュアルとして利用可能 – コーディング力が向上• 若手、新人の教育向けに適用できる 8
    • アジェンダ 何故 単体テスト自動化 が必要? 単体テスト自動化 のコツ 単体テストを効率化するツール群 まとめ 参考
    • 単体テストの対象を明確化する• データの入出力ポイントに対して単 体テストを実施する モデルのテストHTML/ Java 画面 コント モデル CSS Script モデル ローラJavaScript で記 JavaScript から コントローラの述したロジック C# へのマッピ テストのテスト ング JavaScript C# 10
    • 単体テスト自動化が容易なインター フェースを定義する 1/3• 従来の ASP.NET Web Forms では、単体テ ストの自動化がきわめて困難 メインコード テストコード
    • 単体テスト自動化が容易なインター フェースを定義する 2/3• ASP.NET MVC で単体テストの自動化が容易に メインコード テストコード
    • 単体テスト自動化が容易なインター フェースを定義する 3/3• Testing Framework や NUnit 等で自動テ スト可能な外部インターフェース設計とする ViewReult コント • ViewBag ローラ • Model Web API の 応答 XXXXResult (その他の応答) 13
    • 変数名の命名規則に留意する 1/2• テストメソッド名、変数名からチェック対象を理解 できるように命名する良い例 [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 ); } 14
    • 変数名の命名規則に留意する 2/2• 「悪い例」では、テストメソッド名、変数名から チェック対象が理解できない悪い例 [TestMethod] public void Index () { HomeController controller = new HomeController(); var actual = (controller.Index() as ViewResult).Model; Assert.Equals(new List<string>(){ "a", "b", "c" }, actual ); } 15
    • 1メソッド・1アサートを心がける 1/2• テスト対象を明確化するため、1メソッド・1アサートを 心がける• if 文, for 文, while 文に Assert はダメ、絶対良い例 string expect = XXXXXX; string actual = null; (中間ロジック) Assert.Eqauls( expect, actual ); 16
    • 1メソッド・1アサートを心がける 2/2• 「悪い例」では、チェックする場所が散って何をチェックして いるか分からない悪い例 string expect = XXXXXX; string actual = null; (中間ロジック) if(flag == true) { Assert.Eqauls( expect, actual ); }else{ Assert.Fail(“ここは通らないはず”); } 17
    • モックを効率的に作成する 1/2• Moq.dll 等を利用して HttpContextBase, IPrincipal, IIdentity 等のモック作成が難しい クラスを作成する [TestMethod()] public void IndexTest01() { • Moq.dll を利用してもス string expect = typeof(RedirectToRouteResult).FullName; string actual; BuyHistoryController target = new BuyHistoryController(new TestOrderRepository()); テップ数が多い //モックの作成 var mockHttpContextBase = new Mock<HttpContextBase>(); • Moq.dll を利用しないと 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); } 18
    • モックを効率的に作成する 2/2• モック作成は行数が伸びるので共通化する[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);} 19
    • 名前空間、クラス名の命名規則に留意する• テスト対象のプロジェクト、クラスが分かりやすいよう に命名規則を規定する – プロジェクト名:MyMVC → MyMVC.Test – クラス名: MyClass → MyClassTest – メソッド名: MyMethod → MyMethodTest• 命名規約に従うことで、 TestDriven.NET を利 用した、メインコード/テストコードの切り替えが可能 – http://www.testdriven.net/quickstart.aspx 20
    • アジェンダ 何故 単体テスト自動化 が必要? 単体テスト自動化 のコツ 単体テストを効率化するツール群 まとめ 参考
    • ツールを利用したテスト効率化したい• 紹介したツール・ライブラリを利用 してテストを自動化するHTML/ Java 画面 コント モデル CSS Script モデル ローラ JavaScript C# 22
    • ツールを利用したテスト効率化(β)• 紹介したツール・ライブラリを利用 してテストを自動化するHTML/ View View コント モデル CSS Model Model ローラ knocko Entity knock AutoM ut.map Frame out.js apper ping.js work JavaScript C# 23
    • ツールを利用したテスト効率化(β)• 紹介したツール・ライブラリを利用 してテストを自動化するHTML/ View View コント モデル QUnit-tap CSS Model Model Testing ローラで単体テス knocko Framework Entity ト自動化 ut.map 単体テスト自動化 knock AutoM Frame out.js appernode.exe ping.js MSTest.exe work JavaScript C# 24
    • 紹介するツール・ライブラリ群• 今回は以下のライブラリ・ツールを紹介 – knockout.js – knockout.mapping.js – AutoMapper – Qunit-tap
    • knockout.js• DOM 要素と JSON オブジェクトのマッピング機能 var viewModel = { left: ko.observable( 30 ), right: ko.observable( 40 ) onblur 等のイベントが発生した }; タイミングで、ViewModel と viewModel.answer = DOM要素で値を同期 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> 26
    • Knockout.mapping.js 1/2• C#/VB.NET の ViewModel と JSON オブジェクト をマッピング { name: “若人”, age: 20} 等のJSONに置換される処理 <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> DOM 要素 と viewModel イ ンスタンスとを双方向バインド 27
    • Knockout.mapping.js 2/2• C#/VB.NET の ViewModel と JSON オブジェクト をマッピング $.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; } 28
    • AutoMapper• Model – ViewModel といったモデル間のマッピ ングを実施する• 複数モデルからの集約化等、細かな制御が可能 Model ViewModel 項目1 項目2
    • 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);
    • 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();
    • アジェンダ 何故 単体テスト自動化 が必要? 単体テスト自動化 のコツ 単体テストを効率化するツール群 まとめ 参考
    • まとめ• ASP.NET MVC は単体テストの自動化に向 いている• 単体テストの自動化を実施するためにはコツ がある• 単体テストの自動化を支援するツールは多々 存在する
    • View と コントローラの構成 (β)HTML/CSS ViewM View knockout.map Contr Model knockout.js Model ping.js odel oller Entity FrameworkHTML/CSS ViewM View knockout.map knockout.js Model ping.js odel ModelHTML/CSS View ViewM Entity knockout.map knockout.js Model ping.js odel Framework 1対N N対M 1対1 対応 対応 対応 対応関係 C# JavaScript
    • アジェンダ 何故 単体テスト自動化 が必要? 単体テスト自動化 のコツ 単体テストを効率化するツール群 まとめ 参考
    • 参考 1/2• InfoQ – ASP.NET MVC のテスト方法 – http://www.infoq.com/jp/news/2012/03/aspnet- unit-test• MSDN Library – ASP.NET MVC アプリケーションの単体テスト – http://msdn.microsoft.com/ja- jp/library/ff936235.aspx• ASP.NET MVC3 における単体テストの基礎 – http://codezine.jp/article/detail/6493• wa りと na はてな日記 - Moq.dll on ASP.NET MVC その2 – http://d.hatena.ne.jp/waritohutsu/20090909/
    • 参考 2/2• knockout.js Documentation > mapping – http://knockoutjs.com/documentation/plugins- mapping.html• knockout.js Documentation > The “template” binding – http://knockoutjs.com/documentation/template- binding.html• knockout.js の注意すべき点 – http://d.hatena.ne.jp/shiba-yan/20120130/• miso_soup3 - AutoMapper+ViewModel In MVC その2 – http://d.hatena.ne.jp/miso_soup3/20120408/
    • 余談!
    • というか続編!
    • クラウド上で単体テスト自動化• Trac Lightning on Windows Azure – https://github.com/normalian/WATracLightning
    • テスト自動化もクラウドへ…単体テスト自動化(手動キック) 単体テストの自動化 (自動キック) 全てクラウドへ・・・
    • 自はこ 動ての テし スな トく 坂遠 をい よ ・ ・ ・未 ばのよオ かぼうレ りりやは だはく かじ完 らめ なた