แนวทางการเขียน Unit Tests ที่ดีสำหรับ C #

ในความคิดของผู้เขียน ผู้พัฒนาส่วนใหญ่มักไม่ชอบที่จะเขียน Unit testing บางคนอาจจะคิดว่ามันน่าเบื่อ หรือบางคนก็ไม่เห็นคุณค่าในการเขียน code เพื่อตรวจสอบการทำงานของ code อื่นๆ Unit testing คือแนวทางในการเขียน code เพื่อตรวจสอบว่าหน่วยการทำงานใน แอปพลิเคชันซอฟต์แวร์ ว่าทำงานตามที่ตั้งใจไว้หรือไม่ เช่น หากตั้งใจที่จะให้ตัวอักษรตัวแรกของคำเป็น พิมพ์ใหญ่ unit test จะต้องสามารถตรวจสอบว่าตัวอักษรตัวแรกเป็นตัวพิมพ์ใหญ่โดยไม่สนใจอักษรตัวอื่นๆ ข้อดีอย่างหนึ่งของการเขียน unit tests ใน C # คือ เราสามารถใช้ Test Explorer ใน Visual Studio เพื่อตรวจสอบว่าการทดสอบทั้งหมดผ่านหรือไม่ โดยที่ไม่ต้องกังวลว่าการเปลี่ยนแปลงล่าสุดที่เขียน จะทำให้ระบบทำงานไม่ได้หรือไม่ การเลือก Testing Framework Testing frameworks ช่วยให้เราสามารถใช้ attribute ในการเขียน unit tests [TestClass] หรือ [TestMethod] ซึ่ง attribute เหล่านี้บอกให้ Text Explorer ใน Visual Studio รู้จัก class หรือ method นั้นคือ unit test และจะรันโค้ดเพื่อตรวจสอบการทำงานว่าผ่านหรือไม่ผ่าน Testing frameworks สำหรับ. NET ที่ได้รับความนิยมคือ MSTest xUnit.NET NUnit การเลือก Testing frameworks ก็เหมือนกับการเลือกรถ บางอันมีประสิทธิภาพสูง บางอันให้ความสะดวกสบาย แต่สุดท้ายทั้งหมดก็ทำงานเพื่อบรรลุเป้าหมายเดียวกัน NUnit เป็น test framework แรกๆที่ได้รับความนิยมสำหรับผู้พัฒนา .NET, เมื่อเปรียบเทียบกับความสามารถของ MSTest ( test framework ของ Microsoft) โดยส่วนใหญ่ก็จะเหมือนกับใน NUnit และ MSTest เป็น test framework ที่ถูกสร้างขึ้นและสามารถใช้งานได้ใน Visual Studio สำหรับ xUnit.NET เป็นน้องใหม่ใน test framework ที่นำเสนอคุณสมบัติเพิ่มเติมและวิธีการที่ง่ายขึ้นในการเขียน unit tests ที่พัฒนาโดย NET Core โดยส่วนใหญ่จะไม่ใช้เวลามากเกินไปในการพิจารณา test framework เพื่อใช้ในโครงการหากโครงการมีการกำหนด test framework ที่เฉพาะเจาะจง ก็ให้ใช้ test framework นั้น ถ้าไม่ได้กำหนด ก็ให้ทำการศึกษาและตัดสินใจเลือก test framework ที่เหมาะกับโครงการ AAA ( Arrange, Act, Assert ) วิธีการเขียน unit test แบบ ‘AAA’ (Arrange, Act, Assert) เป็นวิธีปฏิบัติในการเขียน unit test และช่วยให้เราสามารถเขียน unit test ในรูปแบบที่ทำซ้ำและเข้าใจได้ Arrange เราจะเริ่มเขียน unit test โดยการจัดเรียง objects ที่ต้องการทดสอบ ซึ่งอาจจะเป็นการ initializing class หรือ การเตรียมข้อมูลในฐานข้อมูลสำหรับทดสอบ หรือการ mocking object โดยการใช้ interface ตัวอย่างด้านล่าง มีกำหนดค่า mock object ของ ILogger<Calc> ให้กับ interface “ILogger” Act เราจะดำเนินการ และเรียกใช้ส่วนของ code หรือ method ที่ต้องการทดสอบโดยการผ่านค่า parameter ให้กับ method และเก็บผลลัพธ์ใน valiable ที่กำหนด ตัวอย่างด้านล่าง เป็นการเรียกใช้ method “Divide” โดยส่ง parameter ไป 2 ตัว และเก็บผลลัพธ์การทำงานในตัวแปร result Assert สุดท้าย

Read More »

เขียน Unit test ทดสอบการทำงานกับฐานข้อมูลที่ใช้ Entity Framework Core

ในบทความนี้ จะนำเสนอการเขียน unit test เพื่อทดสอบการทำงานของ method ที่ใช้งาน Entity Framework Core ซึ่งตัว Entity Framework Core มาพร้อมความสามารถที่สามารถใช้งาน in-memory store ซึ่งสามารถใช้ในการทดสอบได้ หรือจะใช้ mock framework ในการทดสอบก็ได้ โดยในบทความนี้จะแสดงให้เห็นทั้งสองแนวทาง In Memory Database In Memory Database เป็นการสร้าง database จำลองขึ้นมาใช้บน memory แทนที่การใช้ database ตัวจริง ทำให้เราสามาถเขียน unit test โดยที่ไม่ไปกระทบกับ database จริงๆ โดยการเพิ่ม Microsoft.Entityframework.InMemory NuGet package เข้าไปใน test projet ในส่วนของ DbContext class จะต้องมี constructor ที่รับ DbContectOption เป็น parameter จากตัวอย่างด้านบน เราใช้ UseInMemoryDatabase extension method -ของ DbContextOptionsBuilder ซึ่งรับ parameter 1 ตัวเพื่อกำหนดชื่อของ database โดยเราจะใช้ Guid จากนั้นก็สามารถเขียน unit test ได้ดังนี้ จากตัวอย่างด้านบน CreateDbContext method ทำหน้าที่ในการสร้าง DbContext object ที่ทำงานกับ in-memory database แทนที่จะใช้งาน database ตัวจริง หลังจากนั้นก็สามารถทำตามที่ต้องการได้ เหมือนกับการใช้งาน DbContext ปกติ Using Mock Frameworks อีกทางเลือกหนึ่ง เราสามารถใช้ mock frameworks ในการเขียน unit tests ซึ่งเราจะใช้ Moq mock frameworks ซึ่งเป็น mock frameworks ที่ได้รับความนิยมสำหรับ .Net platform โดยก่อนที่จะเริ่มเขียน unit test เราจะต้องกำหนดให้ DbSet pproperty ของ DbContext เป็น virtual ซึงจะทำให้ Moq framework สามารถสร้าง fake object และ override property นี้ได้ และดำเนินการดังนี้ สร้าง generic collection สำหรับ DbSet property แต่ละตัว Config fake DbSet ใน mock framework Setup และ forward DbSet property เหล่านั้นไปที่ generic collection Provider Expression ElementType GetEnumerator() อ้างอิง : https://www.bitiniyan.com/2019/02/02/how-to-write-unit-tests-with-entity-framework-core/

Read More »

ข้อมูลใน DropdownList แรกจนถึง DropdownList สุดท้ายกับค่าที่เหลืออยู่ของเขา ด้วย LINQ

ในช่วงที่ผ่านมา ได้มีการพัฒนาระบบโดยมีการนำ LinQ มาใช้นิด ๆ หน่อย ๆ (มือใหม่หัดใช้ >< ) ซึ่งมีอยู่ฟังก์ชันนึงที่เกี่ยวกับ การ Bind ค่า DropdownList กรณีที่มี DropdownList หลาย ๆ ตัวและไม่อยากให้ค่าที่เคยเลือกจาก DropdownList ก่อนหน้าไปแสดงใน DropdownList ถัดไปอีก น่าสนใจทดลองใช้แล้วทำงานได้ดี ผู้เขียนจึงนำมาเขียนเพื่อไว้เตือนความจำ จะได้กลับมาอ่าน แนวคิดและวิธีการดังนี้ค่ะ ในขั้นตอนแรก สร้าง Data ที่ชื่อว่า MyList เก็บข้อมูล id และชื่อ เพื่อเตรียมเป็น DataSource สำหรับ Bind ให้กับ DropdownList1 ดังนี้ ต่อมากำหนดค่าให้กับ MyList เพื่อผูกให้กับ DropdownList1 ผลลัพธ์ของ DropdownList1 ได้ดังนี้ ID Name1 name12 name23 name35 name510 name10 ต่อมา กำหนดว่า DropdownList1 เลือกค่าเป็น ID = ‘2’ จากนั้น ที่ Event SelectedIndexChange ของ DropdownList1 ให้ใส่ Code ดังนี้ จากนั้นผูก myDataSource ให้กับ DropdownList2 ค่าล่าสุดใน DropdownList2 จะแสดงดังด้านล่าง โดยที่ ID = ‘2’ จะหายไป เนื่องจากถูกเลือกไปแล้ว ดังนี้ ID Name 1 name1 3 name3 5 name5 10 name10 กรณีที่มี DropdownList3 ก็ให้ทำเหมือนขั้นตอนก่อนหน้า ตัวอย่างกำหนดค่าการเลือกของ DropdownList1 = ‘2’ และ DropdownList2 = ‘5’ ดังนี้ จากนั้น ที่ Event SelectedIndexChange ของ DropdownList2 ให้ใส่ Code แบบเดิม จากนั้นผูก myDataSource ให้กับ DropdownList3 ค่าล่าสุดใน DropdownList3 จะแสดงดังด้านล่าง โดยที่ ID = ‘2’ และ ‘5’ จะหายไป เนื่องจากถูกเลือกไปแล้ว ดังนี้ ID Name 1 name1 3 name3 10 name10 จะเห็นได้ว่าเราใช้ Query เดียวกันในหลาย ๆ DropdownList ดังนั้นสามารถทำ Query นี้ให้เป็นฟังก์ชันเพื่อเรียกใช้งานได้ หวังว่าจะเป็นประโยชน์ไม่มากก็น้อยสำหรับผู้อ่านนะคะ \(@^0^@)/

Read More »

Crystal Report : Suppress การซ่อน/แสดง Section

ปกติแล้วการจัดรายงานใน Crystal Report จะมีการแบ่งเป็น 5 ส่วนดังนี้ค่ะ Report Header Section เป็นส่วนที่อยู่บนส่วนหัวรายงาน แสดงแค่หน้าแรกเพียงหน้าเดียวเท่านั้น Page Header Section เป็นส่วนที่แสดงต่อจากส่วน Report Header Section แสดงอยู่ทุกหน้า Details Section ส่วนแสดงรายละเอียดที่ต้องการ สามารถจัดกลุ่มข้อมูล แบ่งรายงานเป็น 2 ส่วนและอื่น ๆ ได้ Page Footer Section เป็นส่วนที่แสดงในรายงานทุกหน้าอยู่บนส่วนท้ายของรายงาน Report Footer Section เป็นส่วนที่อยู่ส่วนท้ายสุดของรายงานจะแสดงแค่หน้าสุดท้ายเท่านั้น ซึ่งในแต่ละ Section นั้นสามารถมี Section ย่อย ๆ ได้มากกว่า 1 Section ย่อยดังภาพ ซึ่งเราสามารถแสดงหรือซ่อน Section ย่อย ๆ เหล่านี้ได้ตามเงื่อนไขที่เราต้องการ โดยใช้เมนู “Suppress” จัดการ ดังนี้ค่ะ คลิกขวาที่ Section ใดก็ได้ เลือกเมนู “Section Expert” จะพบกับหน้าจอ Section Expert ดังภาพโดยหน้าจอจะแบ่งเป็น 2 ส่วน 👈 ซ้ายมือ เป็นส่วนแสดงรายการ section ทั้งหมดของเราที่มีสามารถเพิ่ม ลบ หรือย้าย Section ขึ้นและลงตามที่ต้องการได้ 👉 ขวามือ จะแบ่งเป็น Tab ย่อย ๆ ในวันนี้ส่วนที่ผู้เขียนต้องการนำเสนออยู่ที่ Tab “Common” ที่ Tab “Common” หาบรรทัดที่ชื่อว่า “Suppress (No Drill-Down)” ดูที่ด้านขวา ถ้าสัญลักษณ์ “x-2” เป็น สีฟ้า แสดงว่า เรา ไม่ได้ มีการเขียนคำสั่งให้ซ่อนตามเงื่อนไข ถ้าสัญลักษณ์ “x-2” เป็น สีแดง แสดงว่า มี การเขียนคำสั่งให้ซ่อนตามเงื่อนไข จากรูปด้านล่างสามารถอธิบายได้ว่า ให้ซ่อน Page Header a โดยไม่มีเงื่อนไข ส่วนรูปด้านล่างสามารถอธิบายได้ว่า ให้ซ่อน Page Header l โดยมีเงื่อนไข ซึ่งสามารถกดเข้าไปดูเงื่อนไขที่เขียนไว้ได้ ส่วนของคำสั่งที่เขียนไว้ สามารถอธิบายได้ดังนี้ เงื่อนไขคือ ถ้า Formula Field “@hdLang” มีค่าเป็น “E” และ ไม่ใช่รายงานหน้าแรก ผลลัพธ์ที่ต้องการ ✅ถ้าตรงตามเงื่อนไข ให้แสดง Page Header l ❌ถ้าไม่ตรงตามเงื่อนไข ให้ซ่อน Section นี้ เพียงเท่านี้ ก็สามารถจัดการการซ่อนหรือแสดง Section ตามเงื่อนไขต่าง ๆ ได้ตามต้องการ o(*°▽°*)o d=====( ̄▽ ̄*)b

Read More »

Crystal Report : Grid กับการจัดรูปแบบรายงาน

ปกติแล้วการจัดรายงานใน Crystal Report ตัวหน้ากระดาษหรือหน้าจอนั้น จะเป็นหน้ากระดาษสีขาวปกติ ทำให้การจัดข้อความที่มีระยะเยื้องนั้นจัดได้ค่อนข้างยาก ตรงกันรึยังนะ หรือยังไม่ตรง นี่คือ 1 ในปัญหาของผู้เขียนเช่นกัน 🤣 ดังนั้นวันนี้ ผู้เขียนจะมาแนะนำการตั้งค่า Grid เพื่อให้การขยับ Object ในรายงานของเราง่ายขึ้น ขั้นตอนดังนี้ค่ะ 1️⃣ คลิกขวาพื้นที่โล่ง ๆ เลือกเมนู “Design” 2️⃣ ต่อด้วยเมนู “Default Setting” 3️⃣ ใน Tab “Layout” สังเกตส่วนด้านขวาที่ชื่อว่า “Grid” 👀 จะพบ Checkbox “Show Grid” ให้ ✅ ไว้ 👀 ในส่วนของ Grid Size เราสามารถกำหนดได้ว่าจะให้ตัวกระดาษรายงานของเราแสดง Grid ถี่แค่ไหน ในที่นี้ผู้เขียนให้ความละเอียดมากสุดเลยกำหนดไว้ที่ 0.157 4️⃣หลังจากกำหนดค่าทุกอย่างเสร็จแล้วกลับมาหน้ารายงานเดิมจะพบว่า หน้าจอเราดำมืด ไม่ต้องตรงใจค่ะ เป็นเพราะค่า Grid ที่เรากำหนดไว้ถี่มาก หน้าจอเลยกลายเป็นท่านเปา วิธีการก็คือ ไปขยายหน้าจอค่ะ โดยไปที่เมนูบาร์ด้านบน จะพบค่าที่ Default อยู่ที่ 200% ให้ขยายเป็น 400% หรือตามที่ต้องการเลยค่ะ ✨หน้าจอหลังจากขยายก็จะเห็นดังภาพนะคะ เราสามารถจัด Object ให้ตรงตามที่เราต้องการได้เล้ย ^^

Read More »