การพัฒนา Unit Testing โดย MSTest test library (.NET Core)

บทความนี้นำเสนอขั้นตอนการพัฒนา Unit Test อย่างง่ายโดยแสดงให่้เห็นการพัฒนาทีละขั้นตอน สำหรับระบบที่พัฒนาบน .NET Core โดยใช้ MSTest เพื่อทำความเข้าใจการพัฒนาแบบ test-driven development (TDD) ซึ่งในขั้นแรก เริ่มต้นด้วยการสร้าง source project ชื่อ “CalcTool” ใช้สำหรับการทดสอบ อยู่ภายใต้ folder “TestSample” ซึ่งขั้นตอนการสร้าง project สามารถดูได้จาก บทความ การพัฒนา Unit Testing โดย xUnit test library (.NET Core) ซึ่งจะได้ class “Calc” ซึ่งประกอบไปด้วย method “AbsAddByOne(int value)” ที่ยังไม่ได้เขียน code การทำงาน สร้าง test project ที่ใช้ MSTest library โดยเปิด command prompt เข้าไปที่ folder “TestSample” และสร้าง sub folder ชื่อ “CalcTool.MSTests” จากนั้นเข้าไปที่ folder “CalcTool.MSTests” ทำการสร้าง .NET Core project โดยใช้คำสั่ง dotnet new mstest โดยคำสั่งนี้จะทำการสร้าง test project ที่ใช้ MSTest test library และกำหนดค่า test runner <ItemGroup> <PackageReference Include=”Microsoft.NET.Test.Sdk” Version=”15.0.0″/> <PackageReference Include=”MSTest.TestAdapter” Version=”1.1.11″/> <PackageReference Include=”MSTest.TestFramework” Version=”1.1.11″/> </ItemGroup> เพิ่ม reference ไปยัง project ที่ต้องการทดสอบซึ่งในที่นี้คือ CalcTool project โดยใช้คำสั่ง dotnet add reference ../CalcTool/CalcTool.csproj จากนั้นให้ execute คำสั่ง dotnet restore เพื่อ restore NuGet package ที่จำเป็นต้องใช้ในแต่ละ project เริ่มพัฒนา unit testing โดยลบ file “UnitTest1.cs” และสร้าง file ใหม่โดยใช้ชื่อว่า “CalcTest.cs” และเขียน code ดังนี้ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace CalcTool.MSTest { [TestClass] public class CalcTest { [TestMethod] public void AbsAddByOneTest() { var c = new Calc(); var result = c.AbsAddByOne(5); Assert.AreEqual(result, 6); } } } *[TestClass] attribute ใช้เพื่อบอกว่ามี unit test อยู่ใน class นั้น *[TestMethod] attribute ใช้เพื่อกำหนดว่า method นั้นๆเป็นแบบ single test ทำการทดสอบโดยการ execute dotnet test ซึ่งจะทำการ build และ start MSTest test runner ซึ่งพบว่าผลการทดสอบ fail เนื่องจากยังไม่ได้ implement code ใน method “AbsAddByOne” ของ class “Calc” ดังนั้นกลับไปที่ method

Read More »

การพัฒนา Unit Testing โดย xUnit test library (.NET Core)

บทความนี้นำเสนอขั้นตอนการพัฒนา Unit Test อย่างง่ายโดยแสดงให่้เห็นการพัฒนาทีละขั้นตอน สำหรับระบบที่พัฒนาบน .NET Core โดยใช้ xUnit เพื่อทำความเข้าใจการพัฒนาแบบ test-driven development (TDD) ซึ่งในขั้นแรก เริ่มต้นด้วยการสร้าง source project ที่จะใช้สำหรับการทดสอบ สร้าง folder “TestSample” และ sub folder ชื่อ “CalcTool”  จากนั้นเปิด command prompt เข้าไปที่ folder “CalcTool” เพื่อทำการสร้าง .NET Core project โดยใช้คำสั่ง dotnet new classlib rename class1.cs เป็นชื่อ calc.cs และเขียน code ดังนี้ using System; namespace CalcTool { public class Calc { public int AbsAddByOne(int value) { throw new NotImplementedException(“Not implemented”); } } } สร้าง test project โดยกลับไปที่ folder “TestSample” และสร้าง sub folder ชื่อ “CalcTool.Tests” จากนั้นเปิด command prompt เข้าไปที่ folder “CalcTool.Tests” เพื่อทำการสร้าง .NET Core project โดยใช้คำสั่ง dotnet new xunit โดยคำสั่งนี้จะทำการสร้าง test project ที่ใช้ xunit test library และกำหนดค่า test runner ไว้ใน CalcTool.Tests.csproj file : CalcTool.Tests.csproj <Project Sdk=”Microsoft.NET.Sdk”> <PropertyGroup> <TargetFramework>netcoreapp1.1</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include=”Microsoft.NET.Test.Sdk” Version=”15.0.0″/> <PackageReference Include=”xunit” Version=”2.2.0″/> <PackageReference Include=”xunit.runner.visualstudio” Version=”2.2.0″/> </ItemGroup> </Project> เพิ่ม reference ไปยัง project ที่ต้องการทดสอบซึ่งในที่นี้คือ CalcTool project โดยใช้คำสั่ง dotnet add reference ../CalcTool/CalcTool.csproj ก่อนที่จะ build CalcTool project หรือ CalcTool.Tests project ต้อง execute คำสั่ง dotnet restore เพื่อ restore NuGet package ที่จำเป็นต้องใช้ในแต่ละ project เริ่มพัฒนา unit testing โดยลบ file “UnitTest1.cs” และสร้าง file ใหม่โดยใช้ชื่อว่า “CalcTest.cs” และเขียน code ดังนี้ using System; using Xunit; using CalcTool; namespace CalcTool.Tests { public class CalcTest { [Fact] public void AbsAddByOneTest() { var c = new Calc(); var result = c.AbsAddByOne(5); Assert.Equal(result, 6); } } } *[Fact]

Read More »

Itextsharp #3 คู่มือเทคนิคพื้นฐานการใช้งาน PdfTable สำหรับมือใหม่ ตอนที่ 1

บทความนี้ผู้เขียนจะพูดถึงส่วนที่มีการทำงานในรูปแบบ Table สำหรับผู้ที่เริ่มต้นใหม่สามารถอ่านบทความ ตอนที่ 1 และ ตอนที่ 2 เพื่อความเข้าใจต่อเนื่องกันนะครับ ก่อนที่ผู้เขียนจะไปพูดถึงส่วนของการเขียนโปรแกรมนั้น ผู้เขียนอยากอธิบายเพื่อทำความเข้าใจให้กับผู้อ่านได้เห็นภาพได้ชัดเจนเกี่ยวลักษณะการทำงานของ Table ใน Itextsharp ต่อจากตอนที่แล้ว ที่ได้พูดถึงไว้แบบคร่าวๆ ตอนนี้เราจะลงรายละเอียดมากขึ้น ว่ามีการทำงานอย่างไร จากรูปตัวอย่างจะเป็นการแสดงส่วนของการทำงานในการสร้างTable ของโปรแกรม Itextsharp โดยเมื่อเราได้ทำการเพิ่ม pdfCell ลงไปใน pdfTable Itextsharp จะทำการนำ pdfCell มาเรียงต่อกันไปเรื่อยๆ และทำการอ้างอิงว่าในแต่ละ Row มีได้กี่ Collumn ตามที่ได้ระบุไว้ตอนสร้าง Table เมื่อมี Cell ครบตามกำหนดจะขึ้นRowใหม่ให้อัตโนมัติ แต่สิ่งที่ควรระวังคือ กรณีที่Rowนั้นๆมี Collumn ไม่ครบตามที่กำหนด โปรแกรมอาจไม่แสดงผลของส่วนนั้นได้ ซึ่งในตัวอย่างผู้เขียนได้กำหนดไว้ 3 Collumn ต่อ Row และได้เพิ่ม pdfCell ไปทั้งหมด 9 อันด้วยกันครับ เมื่อทำการแสดงผลจะได้ Table ที่มีขนาด 3×3 นั้นเอง PdfPTable PdfTable = new PdfPTable(3);//#1 float[] tbwidths = { 50f, 50f, 50f}; PdfTable.SetWidths(tbwidths); PdfTable.WidthPercentage = 100; PdfPCell PdfCell = null; PdfCell = new PdfPCell(new Phrase(new Chunk(“1”, bold)));//#2 PdfCell.HorizontalAlignment = Element.ALIGN_CENTER; PdfTable.AddCell(PdfCell); PdfCell = new PdfPCell(new Phrase(new Chunk(“2”, bold)));//#3 PdfCell.HorizontalAlignment = Element.ALIGN_CENTER; PdfTable.AddCell(PdfCell); PdfCell = new PdfPCell(new Phrase(new Chunk(“3”, bold)));//#4 PdfCell.HorizontalAlignment = Element.ALIGN_CENTER; PdfTable.AddCell(PdfCell); PdfCell = new PdfPCell(new Phrase(new Chunk(“4”, bold)));//#5 PdfCell.HorizontalAlignment = Element.ALIGN_CENTER; PdfTable.AddCell(PdfCell); PdfCell = new PdfPCell(new Phrase(new Chunk(“5”, bold)));//#6 PdfCell.HorizontalAlignment = Element.ALIGN_CENTER; PdfTable.AddCell(PdfCell); PdfCell = new PdfPCell(new Phrase(new Chunk(“6”, bold)));//#7 PdfCell.HorizontalAlignment = Element.ALIGN_CENTER; PdfTable.AddCell(PdfCell); PdfCell = new PdfPCell(new Phrase(new Chunk(“7”, bold)));//#8 PdfCell.HorizontalAlignment = Element.ALIGN_CENTER; PdfTable.AddCell(PdfCell); PdfCell = new PdfPCell(new Phrase(new Chunk(“8”, bold)));//#9 PdfCell.HorizontalAlignment = Element.ALIGN_CENTER; PdfTable.AddCell(PdfCell); PdfCell = new PdfPCell(new Phrase(new Chunk(“9”, bold)));//#10 PdfCell.HorizontalAlignment = Element.ALIGN_CENTER; PdfTable.AddCell(PdfCell); จาก code ด้านบนผู้เขียนได้ทำการสร้าง Table ขึ้นมาโดยกำหนดขนาด Collumn ไว้เท่ากับ 3 (#1)และทำการกำหนดขนาดความกว้างของ Collumn ในบรรทัดถัดมา เมื่อทำการสร้าง Table เรียบร้อยแล้วผู้เขียนก็ทำการสร้างและเพิ่ม Cell ลงใน Table ไล่ลงมาตามลำดับใน Code (#2-#10) แค่นี้เราก็ได้ Table ตามรูปตัวอย่างแล้วครับ

Read More »

การส่งค่าจาก Models แบบ Multiple มายัง Single View

โดยปกติแล้วใน MVC เราจะไม่สามารถส่งค่าที่อยู่ใน Models มามากกว่า 1 Models จาก Controller มายังวิวเดียวกันได้ ซึ่งจริงๆ แล้วมีเทคนิคที่จะทำให้สามารถส่งค่าผ่านมาได้โดยง่าย ดังหลายๆ วิธีต่อไปนี้   ดาวน์โหลด Source Code ได้ที่นี่ครับ   หมายเหตุ: ในตัวอย่างผมจะใช้ method GetTeachers() และ GetStudents() ร่วมกันในหลายวิธีนะครับ ตามนี้ครับ   1. ใช้ View Model View Model เป็น Class เดี่ยวๆ ที่อาจจะประกอบด้วยหลาย models อยู่ภายใน ซึ่งไม่ควรจะมี method อยู่ภายใน จากตัวอย่างข้างล่าง เป็น model ที่มี 2 properties ซึ่งจะต้องทำการ define strongly typed เพื่อให้ Intellisense สามารถใช้งานได้ Controller View   2.ใช้ View Data การใช้ ViewData เป็นอะไรที่ง่ายมาก สามารถเก็บค่าและส่งค่าผ่านจาก Controller ไปยัง View ได้ทันที (คล้ายกับตัวแปล Session ใน C# รุ่นก่อนๆ) ดังตัวอย่าง Controller   View   3.ใช้ Dynamic Model จะต้องทำการเรียกใช้คลาส ExpandoObject (อยู่ภายใต้ namespace: System.Dynamic เฉพาะใน .NET Framework 4.0 ขึ้นไป) จะอนุญาตให้เราเพิ่มหรือลบค่า properties ของ object ขณะ runtime ซึ่งจะทำให้เราสามารถสร้าง object และ เพิ่มหรือลบ ค่าเข้าไปใน properties ได้ ซึ่งมีข้อเสียคือการส่งค่าแบบ dynamic นี้จะไม่สามารถใช้ strongly typed model ได้ ซึ่งจะต้องนำไป cast เป็น type ที่ต้องการ เมื่อเรียกใช้อีกครั้งหนึ่ง Controller View     4. ใช้ View Bag จะเหมือนกับการใช้ View Data ซึ่ง View Data เป็น dictionary object ต่างจาก View Bag ที่เป็น dynamic property ของ ControllerBase Class Controller View   5. ใช้ Tuple Tuple คือ Object ที่ไม่สามารถเปลี่ยนรูปได้ (Immutable), ขนาดคงที่และเรียงตามลำดับ (fixed-size and ordered sequence object) โดยโครงสร้างจะมีหมายเลขที่เจาะจงและลำดับที่ของข้อมูล โดย .NET Framework รองรับได้สูงสุด 7 ข้อมูล (elements) ดังตัวอย่าง Controller View   6. ใช้การ Partial View (Partial Render in Action Method) ทำการ render partial view อยู่ภายในวิว ซึ่งเราสามารถแยกเป็นสอง partial view โดยแต่ละ partial view ก็จะมี model เป็นของจนเอง ตามตัวอย่าง Controller View  

Read More »

Fixed Table Header Scrolling

ในปัจจุบันในการพัฒนา website  เราจะเห็นว่า Table เกือบจะเป็นส่วนหนึ่งในการพัฒนาของแต่ละหน้า  ซึ่งส่วนใหญ่จะเป็นการแสดงผลของการค้นหาข้อมูลต่างๆของเมนูหรือหัวข้อในแต่ล่ะเรื่อง บ้างก็อาจจะมีข้อมูลน้อย บ้างก็อาจจะมีข้อมูลเยอะ ทำให้การแสดงผลมีความยาวล้นหน้าเพจ ถึงแม้ว่าปัจจุบันจะมีการนำ paging มาใช้แต่ในบางกรณีอาจจะมีความจำเป็นที่ต้องการตรวจสอบข้อมูลในการค้นหาทั้งหมดในหน้าเดียวกัน  แต่ปัญหาที่ตามมาในการแสดงผลทั้งหมดในหน้าเดียวกันก็คือเมื่อเรา scroll ลงมาข้างล่างสุด Header ของตัวตารางจะไม่ Fixed ไว้ และเลื่อนหายไปข้างบน ทำให้ยากลำบากในการตรวจสอบข้อมูล เนื่องจากผู้ใช้งานอาจจะลืมว่าคอลัมภ์ที่กำลังตรวจสอบอยู่นั้นคือคอลัมภ์อะไร จึงต้อง scroll ขึ้นไปดู Header อีกครั้ง ทำให้มีความล่าช้าในการตรวจสอบข้อมูล วันนี้จึงนำวิธีการ Fixed Header ของตาราง โดยใช้ css มาเสนอเพื่อเป็นแนวทางในการพัฒนากับผู้อ่าน ดังนี้ค่ะ   ตัวอย่างที่1 (CSS ในหน้า Html เดียวกัน)) tbody { display:block; height:400px; overflow:auto; } thead, tbody tr { display:table; width:100%; table-layout:fixed; } thead { width: calc( 100% – 1em ) } ตัวอย่างที่1(การเรียกใช้ CSS ในหน้า Html เดียวกัน) <table id=”tableSearch” class=”table table-responsive table-hover” style=”border-collapse:collapse;border:1px solid #C0C0C0;table-layout:auto;width:1500px;”> <thead> <tr class=”filters” style=”background-color:#C0C0C0″> <th align=”left”>Order</th> <th align=”left”>Name</th> </tr></thead> <tbody><tr> <td colspan=”14″ style=”text-align:center;color:#808080 “>Order</td> <td colspan=”14″ style=”text-align:center;color:#808080 “>Name</td> </tr></tbody> </table> ตัวอย่างที่2 (CSS) html, body{ margin:0; padding:0; height:100%; } section { position: relative; border: 1px solid #000; padding-top: 37px; background: #500; } section.positioned { position: absolute; top:100px; left:100px; width:800px; box-shadow: 0 0 15px #333; } .container { overflow-y: auto; height: 200px; } table { border-spacing: 0; width:100%; } td + td { border-left:1px solid #eee; } td, th { border-bottom:1px solid #eee; background: #ddd; color: #000; padding: 10px 25px; } th { height: 0; line-height: 0; padding-top: 0; padding-bottom: 0; color: transparent; border: none; white-space: nowrap; } th div{ position: absolute; background: transparent; color: #fff; padding: 9px 25px; top: 0; margin-left: -25px; line-height: normal;

Read More »