Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
基礎から見直す ASP.NET MVC   の単体テスト自動化方法~ Windows Azure 関連もあるかも~   Microsft MVP for Windows Azure                          割と普通  ...
自己紹介• 割と普通 ( @normalian ) – Windows Azure のコミュニティメンバ   • Japan Windows Azure User Group     http://r.jazug.jp/ – わんくま同盟 のコ...
本セッションの目的とゴール• 目的 – C#/VB.NET で単体テスト自動化するため、どのよ   うにテストコードを記述すれば良いかを認知 – 単体テスト自動化を支援するツール、ライブラリ群を   認知• ゴール – C#/VB.NET で、...
アジェンダ 何故 単体テスト自動化 が必要?  単体テスト自動化 のコツ  単体テストを効率化するツール群  まとめ 参考
何で単体テスト自動化が必要?• 良く言われるのは以下のメリット – 単体テストの工数を削減できる – コードの保守・再利用性が向上する – コードが綺麗になる                      5
単体テストの工数を削減できる仕様変更が増える程、単体  テスト工数は増大                  6
コードの保守・再利用性が向上する• 変更に伴うデグレを瞬時に検知できる – リファクタリングや保守が容易 – 単体テストコードの動作検証がいつでも可能• 外部仕様が容易に理解できる – メソッドの外部仕様がテストコードに記載 – ドキュメント・...
コードが綺麗になる• ソースコードのテスタビリティが向上する – 単体テストの自動化を意識したインターフェースの定   義を強制 – テストコードをマニュアルとして利用可能 – コーディング力が向上• 若手、新人の教育向けに適用できる     ...
アジェンダ 何故 単体テスト自動化 が必要?  単体テスト自動化 のコツ  単体テストを効率化するツール群  まとめ 参考
単体テストの対象を明確化する• データの入出力ポイントに対して単  体テストを実施する   モデルのテストHTML/   Java       画面      コント    モデル CSS    Script     モデル     ローラJa...
単体テスト自動化が容易なインター   フェースを定義する 1/3• 従来の ASP.NET Web Forms では、単体テ  ストの自動化がきわめて困難  メインコード  テストコード
単体テスト自動化が容易なインター  フェースを定義する 2/3• ASP.NET MVC で単体テストの自動化が容易に   メインコード   テストコード
単体テスト自動化が容易なインター   フェースを定義する 3/3• Testing Framework や NUnit 等で自動テ  スト可能な外部インターフェース設計とする             ViewReult   コント       ...
変数名の命名規則に留意する 1/2• テストメソッド名、変数名からチェック対象を理解  できるように命名する良い例 [TestMethod] public void Indexがリストを返す() {    List<string> expect...
変数名の命名規則に留意する 2/2• 「悪い例」では、テストメソッド名、変数名から  チェック対象が理解できない悪い例 [TestMethod] public void Index () {    HomeController controll...
1メソッド・1アサートを心がける 1/2• テスト対象を明確化するため、1メソッド・1アサートを  心がける• if 文, for 文, while 文に Assert はダメ、絶対良い例 string expect = XXXXXX; str...
1メソッド・1アサートを心がける 2/2• 「悪い例」では、チェックする場所が散って何をチェックして  いるか分からない悪い例 string expect = XXXXXX; string actual = null; (中間ロジック) if(...
モックを効率的に作成する 1/2• Moq.dll 等を利用して HttpContextBase,  IPrincipal, IIdentity 等のモック作成が難しい  クラスを作成する [TestMethod()] public void ...
モックを効率的に作成する 2/2• モック作成は行数が伸びるので共通化する[TestMethod()]public void IndexTest01(){   string expected= typeof(RedirectToRouteRes...
名前空間、クラス名の命名規則に留意する• テスト対象のプロジェクト、クラスが分かりやすいよう  に命名規則を規定する – プロジェクト名:MyMVC → MyMVC.Test – クラス名: MyClass → MyClassTest – メソ...
アジェンダ 何故 単体テスト自動化 が必要?  単体テスト自動化 のコツ  単体テストを効率化するツール群  まとめ 参考
ツールを利用したテスト効率化したい• 紹介したツール・ライブラリを利用  してテストを自動化するHTML/   Java     画面    コント   モデル CSS    Script   モデル   ローラ                ...
ツールを利用したテスト効率化(β)• 紹介したツール・ライブラリを利用  してテストを自動化するHTML/    View          View    コント   モデル CSS     Model         Model   ローラ...
ツールを利用したテスト効率化(β)• 紹介したツール・ライブラリを利用  してテストを自動化するHTML/  View    View      コント モデル QUnit-tap CSS   Model   Model   Testing  ...
紹介するツール・ライブラリ群• 今回は以下のライブラリ・ツールを紹介 –   knockout.js –   knockout.mapping.js –   AutoMapper –   Qunit-tap
knockout.js• DOM 要素と JSON オブジェクトのマッピング機能 var viewModel = {    left: ko.observable( 30 ),    right: ko.observable( 40 )    ...
Knockout.mapping.js 1/2• C#/VB.NET の ViewModel と JSON オブジェクト  をマッピング             { name: “若人”, age: 20}                   ...
Knockout.mapping.js 2/2• C#/VB.NET の ViewModel と JSON オブジェクト  をマッピング   $.ajax({     type:“POST”, dataType: "json",     con...
AutoMapper• Model – ViewModel といったモデル間のマッピ  ングを実施する• 複数モデルからの集約化等、細かな制御が可能    Model                ViewModel     項目1     項目2
AutoMapper• 「XXX.ID = YYY.ID」の羅列を防止できる• マッピングが存在しない場合は一括でチェック可能 Product product = ProductRepository.GetById(id); Mapping.A...
QUnit-tap の利用• node.exe から実行可能な QUnit – node.exe → Node.js の Windows 実装 – QUnit → ブラウザ上で JavaScript を単体テスト• knockout.js の ...
アジェンダ 何故 単体テスト自動化 が必要?  単体テスト自動化 のコツ  単体テストを効率化するツール群  まとめ 参考
まとめ• ASP.NET MVC は単体テストの自動化に向  いている• 単体テストの自動化を実施するためにはコツ  がある• 単体テストの自動化を支援するツールは多々  存在する
View と コントローラの構成 (β)HTML/CSS                        ViewM                View knockout.map       Contr   Model    knockout...
アジェンダ 何故 単体テスト自動化 が必要?  単体テスト自動化 のコツ  単体テストを効率化するツール群  まとめ 参考
参考 1/2• InfoQ – ASP.NET MVC のテスト方法   – http://www.infoq.com/jp/news/2012/03/aspnet-     unit-test• MSDN Library – ASP.NET ...
参考 2/2• knockout.js Documentation > mapping   – http://knockoutjs.com/documentation/plugins-     mapping.html• knockout.js...
余談!
というか続編!
クラウド上で単体テスト自動化• Trac Lightning on Windows Azure  – https://github.com/normalian/WATracLightning
テスト自動化もクラウドへ…単体テスト自動化(手動キック) 単体テストの自動化 (自動キック)   全てクラウドへ・・・
自はこ    動ての    テし    スな    トく    坂遠    をい    よ    ・    ・    ・未          ばのよオ          かぼうレ          りりやは          だはく      ...
Upcoming SlideShare
Loading in …5
×

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

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

  • Be the first to comment

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

  1. 1. 基礎から見直す ASP.NET MVC の単体テスト自動化方法~ Windows Azure 関連もあるかも~ Microsft MVP for Windows Azure 割と普通 1
  2. 2. 自己紹介• 割と普通 ( @normalian ) – Windows Azure のコミュニティメンバ • Japan Windows Azure User Group http://r.jazug.jp/ – わんくま同盟 のコミュニティメンバ • http://www.wankuma.com/ – Microsoft MVP for Windows Azure 2010~ 2
  3. 3. 本セッションの目的とゴール• 目的 – C#/VB.NET で単体テスト自動化するため、どのよ うにテストコードを記述すれば良いかを認知 – 単体テスト自動化を支援するツール、ライブラリ群を 認知• ゴール – C#/VB.NET で、単体テストの自動化が可能なテ ストコードを効率的に記述することができる 3
  4. 4. アジェンダ 何故 単体テスト自動化 が必要? 単体テスト自動化 のコツ 単体テストを効率化するツール群 まとめ 参考
  5. 5. 何で単体テスト自動化が必要?• 良く言われるのは以下のメリット – 単体テストの工数を削減できる – コードの保守・再利用性が向上する – コードが綺麗になる 5
  6. 6. 単体テストの工数を削減できる仕様変更が増える程、単体 テスト工数は増大 6
  7. 7. コードの保守・再利用性が向上する• 変更に伴うデグレを瞬時に検知できる – リファクタリングや保守が容易 – 単体テストコードの動作検証がいつでも可能• 外部仕様が容易に理解できる – メソッドの外部仕様がテストコードに記載 – ドキュメント・コードの二重化を防止 7
  8. 8. コードが綺麗になる• ソースコードのテスタビリティが向上する – 単体テストの自動化を意識したインターフェースの定 義を強制 – テストコードをマニュアルとして利用可能 – コーディング力が向上• 若手、新人の教育向けに適用できる 8
  9. 9. アジェンダ 何故 単体テスト自動化 が必要? 単体テスト自動化 のコツ 単体テストを効率化するツール群 まとめ 参考
  10. 10. 単体テストの対象を明確化する• データの入出力ポイントに対して単 体テストを実施する モデルのテストHTML/ Java 画面 コント モデル CSS Script モデル ローラJavaScript で記 JavaScript から コントローラの述したロジック C# へのマッピ テストのテスト ング JavaScript C# 10
  11. 11. 単体テスト自動化が容易なインター フェースを定義する 1/3• 従来の ASP.NET Web Forms では、単体テ ストの自動化がきわめて困難 メインコード テストコード
  12. 12. 単体テスト自動化が容易なインター フェースを定義する 2/3• ASP.NET MVC で単体テストの自動化が容易に メインコード テストコード
  13. 13. 単体テスト自動化が容易なインター フェースを定義する 3/3• Testing Framework や NUnit 等で自動テ スト可能な外部インターフェース設計とする ViewReult コント • ViewBag ローラ • Model Web API の 応答 XXXXResult (その他の応答) 13
  14. 14. 変数名の命名規則に留意する 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
  15. 15. 変数名の命名規則に留意する 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
  16. 16. 1メソッド・1アサートを心がける 1/2• テスト対象を明確化するため、1メソッド・1アサートを 心がける• if 文, for 文, while 文に Assert はダメ、絶対良い例 string expect = XXXXXX; string actual = null; (中間ロジック) Assert.Eqauls( expect, actual ); 16
  17. 17. 1メソッド・1アサートを心がける 2/2• 「悪い例」では、チェックする場所が散って何をチェックして いるか分からない悪い例 string expect = XXXXXX; string actual = null; (中間ロジック) if(flag == true) { Assert.Eqauls( expect, actual ); }else{ Assert.Fail(“ここは通らないはず”); } 17
  18. 18. モックを効率的に作成する 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
  19. 19. モックを効率的に作成する 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
  20. 20. 名前空間、クラス名の命名規則に留意する• テスト対象のプロジェクト、クラスが分かりやすいよう に命名規則を規定する – プロジェクト名:MyMVC → MyMVC.Test – クラス名: MyClass → MyClassTest – メソッド名: MyMethod → MyMethodTest• 命名規約に従うことで、 TestDriven.NET を利 用した、メインコード/テストコードの切り替えが可能 – http://www.testdriven.net/quickstart.aspx 20
  21. 21. アジェンダ 何故 単体テスト自動化 が必要? 単体テスト自動化 のコツ 単体テストを効率化するツール群 まとめ 参考
  22. 22. ツールを利用したテスト効率化したい• 紹介したツール・ライブラリを利用 してテストを自動化するHTML/ Java 画面 コント モデル CSS Script モデル ローラ JavaScript C# 22
  23. 23. ツールを利用したテスト効率化(β)• 紹介したツール・ライブラリを利用 してテストを自動化するHTML/ View View コント モデル CSS Model Model ローラ knocko Entity knock AutoM ut.map Frame out.js apper ping.js work JavaScript C# 23
  24. 24. ツールを利用したテスト効率化(β)• 紹介したツール・ライブラリを利用 してテストを自動化する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
  25. 25. 紹介するツール・ライブラリ群• 今回は以下のライブラリ・ツールを紹介 – knockout.js – knockout.mapping.js – AutoMapper – Qunit-tap
  26. 26. 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
  27. 27. 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
  28. 28. 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
  29. 29. AutoMapper• Model – ViewModel といったモデル間のマッピ ングを実施する• 複数モデルからの集約化等、細かな制御が可能 Model ViewModel 項目1 項目2
  30. 30. 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);
  31. 31. 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();
  32. 32. アジェンダ 何故 単体テスト自動化 が必要? 単体テスト自動化 のコツ 単体テストを効率化するツール群 まとめ 参考
  33. 33. まとめ• ASP.NET MVC は単体テストの自動化に向 いている• 単体テストの自動化を実施するためにはコツ がある• 単体テストの自動化を支援するツールは多々 存在する
  34. 34. 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
  35. 35. アジェンダ 何故 単体テスト自動化 が必要? 単体テスト自動化 のコツ 単体テストを効率化するツール群 まとめ 参考
  36. 36. 参考 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/
  37. 37. 参考 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/
  38. 38. 余談!
  39. 39. というか続編!
  40. 40. クラウド上で単体テスト自動化• Trac Lightning on Windows Azure – https://github.com/normalian/WATracLightning
  41. 41. テスト自動化もクラウドへ…単体テスト自動化(手動キック) 単体テストの自動化 (自動キック) 全てクラウドへ・・・
  42. 42. 自はこ 動ての テし スな トく 坂遠 をい よ ・ ・ ・未 ばのよオ かぼうレ りりやは だはく かじ完 らめ なた

×