Day: July 12, 2017

  • การพัฒนา 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] attribute ใช้กำหนดว่า method นั้นๆเป็นแบบ single test

    ทำการทดสอบโดยการ execute dotnet test ซึ่งจะทำการ build และ start xUnit test runner ซึ่งพบว่าผลการทดสอบ fail เนื่องมาจากยังไม่ได้ implement code ใน method “AbsAddByOne” ของ class “Calc” ดังนั้นกลับไปที่ method “AbsAddByOne” เพิ่ม code ลงไปเพื่อให้ผลการทดสอบถูกต้อง/ผ่าน (test pass)

            public int AbsAddByOne(int value)
            {
                return Math.Abs(value) + 1;
                //throw new NotImplementedException("Not implement");
            }
    

    กลับไปที่ folder “CalcTool.Tests” และ execute dotnet test ซึ่งจะทำการ build และ start xUnit test runner ซึ่งพบว่า ผ่านการทดสอบ (test pass)

    ใน xUnit ยังมี attribute ที่ใช้กำหนด suite of tests ซึ่ง execute code เดียวกันแต่มี input ที่มีค่าแตกต่างกันนั่นคือ [Theory] attribute และใช้ [InlineData] attribute ในการกำหนดค่าของ input

            [Theory]
            [InlineData(5)]
            [InlineData(-5)]
            public void AbsAddByOneTest2(int value)
            {
                var c = new Calc();
                var result = c.AbsAddByOne(value);
    
                Assert.Equal(result, 6);
            }
    

    การพัฒนาในรูปแบบ test-driven development (TDD) จะทำเป็นรอบๆในลักษณะนี้โดย เพิ่ม unit testing , เพิ่ม code ใหม่เข้าไป ทดสอบ unit test จนผ่านและเริ่มรอบใหม่ จนกระทั่งได้ test ชุดสุดท้ายและโปรแกรม/library ที่สมบูรณ์ ก็เป็นอันจบการพัฒนาในรูปแบบ test-driven development (TDD)

  • 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 ตามรูปตัวอย่างแล้วครับ หลังจากตัวอย่างแรกผ่านไป ก็มาต่อกันที่ตัวอย่างต่อไปที่ใครใช้งาน Table ก็จำเป็นต้องได้ใช้ฟังก์ชั่นนี้แน่นอน นั้นก็คือ Colspan กับ rowspan นั้นเอง ตัวอย่างนี้จะให้ดูการจัดงานฟังก์ชั่นและการจัดวางลำดับของ Cell เพื่อให้แสดงผลตรงตามที่เราต้องการโดยเริ่มจากฟังก์ชั่น colspan กันก่อนดังนี้

    จากตัวอย่างเป็นการรวม collumn ที่ 1 และ 2 เข้าด้วยกัน และมี column 3-8 เป็นแบบปกติ การเขียนโปรแกรมนั้นให้ยึดเอา collumn แรกที่ทำการรวมCell เป็นจุดเริ่มต้นในการเขียนฟังก์ชั่น Colspan ซึ่งในรูปก็คือ Cell ที่ 1 นั้นเอง

    PdfPTable PdfTable = new PdfPTable(3);
    float[] tbwidths = { 50f, 50f, 50f};
    PdfTable.SetWidths(tbwidths);
    PdfTable.WidthPercentage = 100;
    PdfPCell PdfCell = null;
    PdfCell = new PdfPCell(new Phrase(new Chunk("1", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfCell.Colspan = 2; <---------------------------------------------------#1
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("2", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("3", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("4", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("5", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("6", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("7", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("8", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfTable.AddCell(PdfCell);
    

    จาก Code ตัวอย่างส่วนที่เป็นฟังก์ชั่นการรวม Cell คือ PdfCell.Colspan (#1) นั้นเองและ Cell ที่เหลือก็เพิ่มปกติเหมือนตัวอย่างแรก ต่อไปจะเป็นตัวอย่างของการใช้งาน Rowspan ตามรูปและ Code ดังนี้

    ตัวอย่าง Code ดังนี้

    PdfPTable PdfTable = new PdfPTable(3);
    float[] tbwidths = { 50f, 50f, 50f};
    PdfTable.SetWidths(tbwidths);
    PdfTable.WidthPercentage = 100;
    PdfPCell PdfCell = null;
    PdfCell = new PdfPCell(new Phrase(new Chunk("1", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfCell.Rowspan = 3; <---------------------------------------------------#1
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("2", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("3", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("4", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("5", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("6", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("7", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfTable.AddCell(PdfCell);
    

    ก็จบในส่วนของ Colspan และ Rowspan ในฟังก์ชั่นที่จะแนะนำต่อไปจะเป็นเรื่องของการทำ Header และ Footer ให้กับ Table ของเรากันครับ โดยฟังก์ชั่นดังกล่าวจะทำการโชว์ Header และ Footer ที่เรากำหนดในทุกๆหน้าที่ Table แสดงผลอยู่ อารมณ์เหมือนกับ Header Footer ใน MSWord ครับ

    จากในรูปตัวอย่างจะแบ่งออกเป็น2ส่วนด้วยกันคือ บล๊อกด้านซ้ายจะเป็นรูปแบบการจัดเรียง Row ของการเขียน Code และบล๊อกด้านขวาจะเป็นการแสดงในการใช้งานจริงบน PDF โดยลักษณะการเขียนนั้น Itextsharp บังคับให้เราเขียน Code ส่วนของ Header และ Footer ก่อนเสมอจากนั้นก็ตามด้วยส่วนของ Body ที่เราต้องการต่อท้ายไปเรื่อยๆ ซึ่งเพิ่มฟังก์ชั่นการทำงานมาเพียงแค่2บรรทัดก็สามารถใช้งานได้แล้วครับ มาดูตัวอย่าง Code กันเลยดีกว่า

    PdfPTable PdfTable = new PdfPTable(3);
    float[] tbwidths = { 50f, 50f, 50f};
    PdfTable.SetWidths(tbwidths);
    PdfTable.WidthPercentage = 100;
    PdfTable.HeaderRows = 2; <----------------------------------------#1
    PdfTable.FooterRows = 1; <----------------------------------------#2
    PdfPCell PdfCell = null;
    PdfCell = new PdfPCell(new Phrase(new Chunk("Headder", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfCell.Colspan = 3;
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("Footer", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfCell.Colspan = 3;
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("body 1", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfCell.Colspan = 3;
    PdfTable.AddCell(PdfCell);
    PdfCell = new PdfPCell(new Phrase(new Chunk("body 2", bold)));
    PdfCell.HorizontalAlignment = Element.ALIGN_CENTER;
    PdfCell.Colspan = 3;
    PdfTable.AddCell(PdfCell);
    

    จาก Code ตัวอย่างจะพบว่ามีฟังก์ชั่นใหม่เพิ่มมา2บรรทัดด้วยกันคือ (#1)ส่วนของการกำหนดให้มี Headder+Footer โดยในฟังก์ชั่นนั้นสังเกตุว่าจะกำหนดให้ HeaderRows=2 แต่พอไปดูส่วนของการสร้าง Cell พบว่ามี Header ที่สร้างแค่อันเดียว เหตุผลที่กำหนดเป็น 2 เพราะการกำหนดส่วนของ Header นั้นต้องรวม footer เข้าไปด้วย ในกรณีตัวอย่างคือมี Header 1 และ Footer 1 รวมกันเป็น 2 และต้องไปกำหนดแยกของ Footer แยกอีกฟังก์ชั่นเพื่อให้ตัว Itextsharp รู้ว่ามี Footer กี่แถวด้วยกัน (#2) หลายท่านอาจสับสน ผู้เขียนจะทำการยกตัวอย่างให้ดูเพื่อความเข้าใจมากขึ้น

    จากตัวอย่างในรูปผู้เขียนได้ยกตัวอย่างกรณีที่เราต้องการ Header 2 แถวและ Footer 1 แถว เวลาเขียน Code ให้กำหนดส่วนของ HeaderRow=3 เนื่องจาก 3 มาจาก (Header)2 + (Footer)1 นั้นเองและหลังจากนั้นก็กำหนด FooterRow =1 ตามที่เราตั้งไว้

    จากรูปตัวอย่างถัดมา เราต้องการ Header 2 แถวและ Footer 2 แถว เวลาเขียน Code ให้กำหนดส่วนของ HeaderRow=4 และหลังจากนั้นก็กำหนด FooterRow =2 ตามที่เราตั้งไว้ เราก็จะได้การแสดงผลตรงตามที่เราต้องการแล้ว แต่กรณีที่เราต้องการ Footer เพียงอย่างเดียวเราสามารถทำได้โดยกำหนด HeaderRow=1 และหลังจากนั้นก็กำหนด FooterRow =1 เราก็จะได้ Footer เป็นที่เรียบร้อยครับ

    สุดท้ายนี้ขอขอบคุณผู้ที่สนใจอ่านบทความของผู้เขียนครับ และสำหรับเนื้อหาที่เขียนในบทความมาจากประสบการณ์และการลองผิดลองถูกจากผู้เขียนเอง ถ้ามีส่วนไหนผิดพลาด ตกหล่น ก็ขออภัยไว้นะที่นี้ด้วยครับ

  • ภาพสวยประกอบบน office ด้วย Pickit

    ในการนำเสนองานต่างๆ สิ่งที่ช่วยให้การนำเสนอดูน่าสนใจมากยิ่งขึ้น คือ รูปภาพและรูปแบบการจัดวาง ซึ่งใน office จะมี Add-in ที่ชื่อว่า Pickit ซึ่งเป็นเป็นเครื่องมือที่ช่วยการค้นหาภาพตามที่เราต้องการนำมาใช้ในงานนำเสนอของเราได้ มาดูขั้นตอนการใช้งานกันเลยค่ะ 

    1.เริ่มต้นเราต้องทำการติดตั้ง Add-in ซึ่งสามารถติดตั้งได้ใน Microsoft office (Word, excel, power point) ในที่นี้จะนำเสนอในส่วนของ power point ไปยังแท็บ INSERT > Store

     

    2.เป็นหน้าจอ Apps for Office ในช่องค้นหา พิมพ์คำว่า “Pickit” เมื่อเจอรายการ “Picket Free Images” ให้กดปุ่ม Add

    3.เมื่อติดตั้งโปรแกรมเรียบร้อย โปรแกรมจะปรากฎอยู่ด้านขวาของหน้าจอ

    4.หากโปรแกรมไม่ขึ้นมาสามารถเรียกใช้โปรแกรมได้ที่ INSERT> My Apps > Pickit Free Images

    5.จากนั้นพิมพ์ชื่อภาพที่ต้องการหรือเลือกภาพตามหมวดหมู่ต้องการได้ ในตัวอย่างนี้ข้อยกตัวอย่าง คำว่า “network” ระบบก็จะแสดงรายการภาพ

    6.จากนั้นเลือกภาพที่ต้องการ ก็กดปุ่ม Insert เพื่อดึงภาพมาใช้ในงานของเรา

     

    เพียงเท่านี้เราก็ได้ภาพสำหรับตกแต่งให้งานนำเสนอของเรา น่าสนใจมากยิ่งขึ้น นอกจากนี้ภาพดังกล่าว ยังเป็น “ภาพฟรี” อีกด้วย