Category: Software Testing

  • Robot Framework Puppeteer

    Robot Framework Puppeteer คืออะไร

    เป็น Library ที่ทำมาครอบ Puppeteer เพื่อให้ Robot framework ใช้งานได้ง่าย โดย Keyword ต่างๆจะเหมือนกับการใช้งาน Selenium Library ทำให้ใครที่ใช้งาน Selenium Library อยู่แล้วสามารถปรับตัว รวมไปจนถึง การเปลี่ยนมาใช้ Puppeteer ทำได้ง่ายเลยค่ะ และหมดปัญหาการที่เราต้องมาคอยอัพเดต Web driver อยู่ตลอด ๆ

    การติดตั้งง่ายมาก ๆ ดูให้ทันหล่ะ 555

    รัน Command เดียวเลยจบ ไม่ต้องโหลด Chrome driver หรือ Setup Path เพิ่มเติมให้ปวดหัว เปิด Command line มาเลยค่ะ แล้วพิมพ์คำสั่ง

    pip install –upgrade robotframework-puppeteerlibrary

    การใช้งาน

    เราลองมารัน code เดิมที่เขียนไว้กันดูดีกว่า (selenium2library) อ้าวเฮ้ย!!! Error ซะงั้น Web driver ไม่ support ต้องอัพเดตอีกแล้ว

    งั้นขอไปอัพเดตแปปนึงนะ ไม่ขอเล่าถึงการอัพเดตแล้วนะ เคยเล่าไว้ตอนนึงแล้ว ไปลองหาอ่านกันดู อิอิ หลังจากอัพเดตแล้วมาลองรันอีกรอบ

    เปลี่ยนที่ Setting จาก Selenium2Library เป็น PuppeteerLibrary จากนั้นลองรันดู

    เปรียบเทียบความเร็วในการประมวลผลระหว่างใช้ Selenium2Library กับ PuppeteerLibrary
    รูปแรกจะเป็นการใช้ Selenium2Library รูปถัดไปจะเป็น PuppeteerLibrary

    จะเห็นได้ว่า PuppeteerLibrary ทำงานได้เร็วกว่า นี่ขนาดรันคำสั่งขนาดน้อย ๆ ไว้ลองกับคำสั่งที่ซับซ้อนแล้วจะมาเล่าให้ฟังค่ะ

  • การเปลี่ยนแปลง Coded UI Test ใน Visual Studio 2019

    Microsoft ได้ประกาศว่า Visual Studio 2019 จะเป็น Visual Studio รุ่นสุดท้ายที่มีฟังก์ชัน Coded UI test

    ทำไมถึงเลิกใช้ Coded UI Test

    Coded UI tests ถูกใช้งานสำหรับการทดสอบการทำงานแบบอัตโนมัติของ web apps และ desktop apps โดยที่ในช่วงหลายปีหลังมานี้ Open source UI testing tools เช่น Selenium และ Appium ที่มีแรงสนับสนุนจาก community ที่เข้มแข็งและกลายเป็นมาตราฐานกลาง ซึ่ง Coded UI tests นั้นก็มีพื้นฐานอยู่บน Selenium นอกจากนี้ทั้ง Selenium และ Appium ยังทำงานข้ามแพลตฟอร์มและรองรับภาษาการเขียนโปรแกรมหลายภาษา

    Microsoft จะยังคงให้การสนับสนุน Coded UI tests ใน Visual Studio 2019 อย่างเต็มที่ในอีกหลายปีในอนาคต แต่จะจำกัดเฉพาะการแก้ไขข้อบกพร่อง จะไม่มีการเพิ่มคุณสมบัติใหม่ โดยที่เราสามารถติดตั้ง Visual Studio รุ่นต่าง ๆ แบบ side by side ซึ่งหมายความว่านักพัฒนาจะสามารถใช้ Visual Studio 2019 สำหรับการทดสอบ Coded UI test ที่มีอยู่ ในขณะที่สามารถใช้ Visual Studio รุ่นใหม่ในอนาคตสำหรับความต้องการการพัฒนาในแบบอื่น ๆ

    กลไกการติดตั้งแบบ side by side ทำให้ CI/CD pipelines  ทำงานได้อย่างราบรื่นโดยไม่หยุดชะงักในขณะที่เปลี่ยนแปลง นี่เป็นเพราะ Coded UI tests ทำงานเป็นส่วนหนึ่งของ CI/CD pipelines ใน Azure DevOps โดยการทดสอบจะทำงานกับ Visual Studio รุ่นใดรุ่นหนึ่งที่ติดตั้งใน agent หรือแพลตฟอร์มทดสอบรุ่นใดรุ่นหนึ่งโดยเฉพาะ  ซึ่งหมายความว่าเราไม่จำเป็นต้องใช้ Azure DevOps server สองรุ่นที่แตกต่างกันเพื่อให้สามารถทดสอบ Coded UI ที่มีอยู่ ในขณะที่มีการเปลี่ยนแปลง

    ทางเลือกที่แนะนำใช้แทน Coded UI Test

    Microsoft แนะนำให้ใช้ Open source UI testing tools Selenium และ Appium มาระยหนึ่งแล้ว ซึ่ง Visual Studio 2019 ถือเป็น Visual Studio รุ่นสุดท้ายที่มีฟังก์ชัน Coded UI test โดยที่ Microsoft แนะนำให้ใช้ Selenium สำหรับการทดสอบเ web application และAppium กับ WinAppDriver สำหรับการทดสอบ Desktop application (WPF, WinForms, Win32) และ UWP apps

    ไม่มีเครื่องมืออัตโนมัติที่จะช่วยย้ายจาก Coded UI test ไปยัง Selenium หรือ Appium ในขณะนี้ เราแนะนำให้การสร้าง unit test ใหม่ ควรใช้ทาง Selenium หรือ Appium ในขณะที่วางแผนการแทนที่ Coded UI test เก่าเป็น Selenium หรือ Appium ให้เสร็จสมบูรณ์ก่อนสิ้นสุดระยะเวลาการสนับสนุนจาก Visual Studio

    Selenium Browser Automation Project

    Selenium เป็นเครื่องมือและไลบรารี สำหรับใช้งานและสนับสนุนการทำงานอัตโนมัติของ web browser มันมีส่วนขยายที่จะจำลองการโต้ตอบของผู้ใช้กับ browser และโครงสร้างพื้นฐานสำหรับการใช้งานข้อกำหนด W3C WebDriver ที่ช่วยให้เราสามารถเขียนรหัสที่สามารถใช้ได้สำหรับ web browser หลักทั้งหมด

    ที่แกนกลางของ Selenium คือ WebDriver เป็น interface สำหรับเขียนชุดคำสั่งที่สามารถเรียกใช้ได้ในเบราว์เซอร์จำนวนมาก นี่ตัวอย่างของชุดคำสั่งแบบง่ายของ c#

    using System;
    using OpenQA.Selenium;
    using OpenQA.Selenium.Firefox;
    using OpenQA.Selenium.Support.UI;
    using SeleniumExtras.WaitHelpers;
    
    class HelloSelenium
    {
        static void Main()
        {
            using (IWebDriver driver = new FirefoxDriver())
            {
                WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
                driver.Navigate().GoToUrl("https://www.google.com/ncr");
                driver.FindElement(By.Name("q")).SendKeys("cheese" + Keys.Enter);
                IWebElement firstResult = wait.Until(ExpectedConditions.ElementExists(By.CssSelector("h3>div")));
                Console.WriteLine(firstResult.GetAttribute("textContent"));
            }
        }
    }  

    ในบทความต่อไป เราจะลงไปในรายละเอียดของสิ่งที่เกิดขึ้นเบื้องหลังเมื่อคุณเรียกใช้รหัสนี้ พร้องทั้งการติดตั้งและใช้ Selenium เป็นเครื่องมือทดสอบอัตโนมัติ

    อ้างอิง
    1. https://devblogs.microsoft.com/devops/changes-to-coded-ui-test-in-visual-studio-2019/
    2. https://selenium.dev/documentation/en/

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

    ในบทความก่อนหน้า ได้พูดถึงการเลือก Testing framework ที่เหมาะสม การเขียน unit test โดยใช้แนวคิดแบบ “AAA” (Arrange, Acr, Assert) และการกำหนดชื่อ method ที่สื่อความหมายเข้าใจได้ง่าย

    Test Initialize & Cleanup

    เมื่อ unit tests ทำการทดสอบ methods ภายใน class ก็จำเป็นต้องสร้าง instance ของ class นั้นๆขึ้นมาก่อน ซึ่งจะเกิดขึ้นหลายๆครั้งใน unit test เพื่อประหยัดเวลาและทรัพยากรของระบบ เราสามารถใช้ [TestInitialize] attribute ของ MSTest เพื่อบอกว่า method นั้นใช้สำหรับกำหนดค่าเริ่มต้น สร้าง instance ของ class ก่อนที่จะเริ่ม run unit tests (หรือ [SetUp] ใน NUnit หรือถ้าใช้ xUnit.net ให้สร้างใน constructor )

    เมื่อการทดสอบจบลง เราจะต้องทำการ cleanup object ต่างๆที่ใช้ในการทดสอบ โดยการใช้ [TestCleanup] attribute ในกรณีที่ใช้ MSTest ([TearDown ใน NUnit หรือ implement IDisposable interface สำหรับกรณีที่ใช้ xUnit.net)

    ตัวอย่างด้านล่าง จะกำหนดให้ method “Initialize” เป็น method ที่ใช้สำหรับสร้าง instance ของ class ที่จะใช้ในการทดสอบ ซึ่งจะถูกเรียกใช้ก่อนการทดสอบจะเริ่มทำงาน

    ILogger _log;
    ICalc _calc;
    
    [TestInitialize]
    public void Initialize()
    {
    	_log = Mock.Of<ILogger<Calc>>();
    	_calc = new Calc(_log);
    }
    
    [TestMethod]
    public void Divide_ShouldThrowArgumentException_IfDivideByZero()
    {
    	double result = _calc.Divide(10, 5);
    	result.ShouldBe(2);
    }
    
    [TestCleanup]
    public void Cleanup()
    {
    	// Optionally dispose or cleanup objects
            _calc = null;
    	...
    }

    Shouldly Assertion Framework

    Shouldly framework จะช่วยให้ unit test ทำได้ง่ายและเข้าใจได้ง่ายขึ้น มันจะช่วยผู้พัฒนาในการเขียนการยืนยันผลการทำงานของ unit tests ซึ่งเมื่อกลับมาดู unit test อีกครั้งสามารถอ่าน code แล้วเข้าใจวัตถุประสงค์และความคาดหวังของการทดสอบ

    เปรียบเทียบความแตกต่างระหว่าง การใช้ Shouldly กับ ไม่ใช่ Shouldly

    With Shouldly

    result.ShouldBe(2);

    Without Shouldly

    Assert.AreEqual(2, result);

    Shouldly สามารถใช้ในการตรวจสอบ exception ว่าเกิดตามที่คาดหวังไว้หรือไม่ และสามารถตรวจสอบ meesage ของ exception ได้

    [TestMethod]
    public void Divide_ShouldThrowArgumentException_IfDivideByZero()
    {
    	Should.Throw<ArgumentException>(() => _calcs.Dicide(10, 0))
    	      .Message
                  .ShouldBe("Divide by zero.");
    }

    Moq Mocking Framework

    การสร้าง object จำลองสำหรับ object ที่ไม่ใช่ object หลักที่จะทำการทดสอบ แทนที่การเรียกใช้ object จริงๆ เช่น logging utility หรือ database จะทำให้การทดสอบทำได้อย่างมีประสิทธิภาพขึ้น ซึ่งการทำแบบนี้ เราต้องใช้ Mocking framework มาช่วย โดยตัวที่ได้รับความนิยมตัวนึงก็คือ Moq framework

    การใช้ Moq framework จะช่วยให่เราสามารถ mock class ต่างๆโดยใช้เพียง interface. ตัวอย่างเช่น การใช้ mock ของ logging utility ใน unit test แทนที่จะสร้างและเรียกใช้ logging utility ตัวจริง

    ILogger log = Mock.Of<ILogger<Calc>>();

    We can also verify if a mock object was invoked inside a method and the amount of times it was invoked:

    [TestMethod]
    public void Divide_LogInformationMethod()
    {
    	ILogger log = Mock.Of<ILogger<Calc>>();
    	ICalc calc = new Calc(log);
    	double result = calc.Divide(10,5);
    	Mock.Get(log).Verify(x => x.Log(
    		LogLevel.Information, 
        	It.IsAny<EventId>(), 
        	It.IsAny<FormattedLogValues>(), 
        	It.IsAny<Exception>(), 
        	It.IsAny<Func<object, Exception, string>>()), 
        	Times.Once);
    }

    อ้างอิง : https://kiltandcode.com/2019/06/16/best-practices-for-writing-unit-tests-in-csharp-for-bulletproof-code/

  • แนวทางการเขียน 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”

    // Arrange
    ILogger log = Mock.Of<ILogger<Calc>>();
    ICalc calc = new Calc(log);

    Act

    เราจะดำเนินการ และเรียกใช้ส่วนของ code หรือ method ที่ต้องการทดสอบโดยการผ่านค่า parameter ให้กับ method และเก็บผลลัพธ์ใน valiable ที่กำหนด

    ตัวอย่างด้านล่าง เป็นการเรียกใช้ method “Divide” โดยส่ง parameter ไป 2 ตัว และเก็บผลลัพธ์การทำงานในตัวแปร result

    // Act
    int result = calc.Divide(10, 5);

    Assert

    สุดท้าย จะเป็นการยืนยันว่าผลลัพธ์ที่ได้จากการทดสอบเป็นไปตามที่ได้คาดหวังไว้หรือไม่

    ตัวอย่างด้านล่าง ตัวแปร “result” ควรที่จะมีค่าเท่ากับ 2

    // Assert
    Assert.AreEqual(2, result);

    การตั้งชื่อ

    เมื่อแนวคิดของ ‘AAA’ เป็นแนวปฏิบัติที่ได้รับความนิยม แต่ในส่วนของการกำหนดชื่อของ method ยังคงแตกต่างกันไปและขึ้นอยู่กับผู้พัฒนา ทีม และองค์กร ซึ่งการกำหนดแนวทางการตั้งชื่อเพื่อใช้กับ unit tests ให้มีความสอดคล้องและความชัดเจน ไปในทางเดียวกัน เป็นความคิดที่ดี ซึ่งการตั้งชื่อควรประกอบไปด้วย

    • method ที่ทดสอบ (เช่น ‘Add’)
    • คำอธิบายสั้น ๆ เกี่ยวกับการทดสอบ (เช่น ‘ShouldThrowArgumentException’)
    • ความคาดหวังของการทดสอบนี้ (เช่น ‘IfDivideByZero’)
    public void Divide_ShouldThrowArgumentException_IfDivideByZero()
    {
        ...
    }

    การกำหนดชื่อในรูปแบบนี้ จะเหมาะสำหรับการดูใน Text Explorer ซึ่งสามารถติดตามและเข้าใจได้อย่างง่ายดายว่า unit tests แต่ละหน่วยคืออะไรโดยไม่ต้องเปิดการทดสอบหน่วย

    แนวทางการเขียน Unit Tests ที่ดีสำหรับ C # ยังไม่หมดเพียงเท่านี้ ในบทความต่อไป เราจะมาดูการทำ Test Initialize & Cleanup และ ตัวช่วยอื่นๆที่ใช้ในการเขียน unit tests

    อ้างอิง : https://kiltandcode.com/2019/06/16/best-practices-for-writing-unit-tests-in-csharp-for-bulletproof-code/

  • เขียน 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

    var options = new DbContextOptionsBuilder<MyDbContext>()
                    .UseInMemoryDatabase(Guid.NewGuid().ToString("N")).Options;
    
    var dbContext = new MyDbContext(options);

    จากตัวอย่างด้านบน เราใช้ UseInMemoryDatabase extension method -ของ DbContextOptionsBuilder ซึ่งรับ parameter 1 ตัวเพื่อกำหนดชื่อของ database โดยเราจะใช้ Guid จากนั้นก็สามารถเขียน unit test ได้ดังนี้

    [TestClass]
    public class MyRepositoryTest
    {
            private MyDbContext CreateDbContext()
            {
                var options = new DbContextOptionsBuilder<MyDbContext>()
                    .UseInMemoryDatabase(Guid.NewGuid().ToString("N")).Options;
    
                var dbContext = new MyDbContext(options);
                return dbContext;
            }
    
           
            [TestMethod]
            public void It_should_add_a_product_successfully()
            {
                //Arrange
                var dbContext = CreateDbContext();
                var rep = new MyRepository(dbContext);
                var product = new Product 
                { 
                   ProductName="Toyota Altis",
                   UnitPrice=900000 
                };
    
                //Act
                var result = rep.Add(product);
               
                //Assert
                Assert.IsTrue(result.ProductID > 0);
    
                //Clean up
                dbContext.Dispose();
            }
    
            [TestMethod]
            public void It_should_update_a_product_successfully()
            {
                //Arrange
                var expected = 950000;
                var dbContext = CreateDbContext();
                var rep = new MyRepository(dbContext);
                var product = new Product 
                { 
                   ProductName="Toyota Altis",
                   UnitPrice=900000 
                };
    
                //Act
                var result = rep.Add(product);
                result.UnitPrice = expected;
                rep.Update(result);
                result = dbContext.Products.First(p=>p.ProductID == result.ProductID);
    
                //Assert
                Assert.AreEqual(expected,result.UnitPrice);
    
                //Clean up
                dbContext.Dispose();
            }
    
            [TestMethod]
            public void It_should_remove_a_product_successfully()
            {
                //Arrange
                var dbContext = CreateDbContext();
                var rep = new MyRepository(dbContext);
                var product = new Product 
                { 
                   ProductName="Toyota Altis",
                   UnitPrice=900000 
                };
    
                //Act
                var result = rep.Add(product);
                rep.Delete(result.ProductID);
                var isExists = dbContext.Products.Any(p => p.ProductID == result.ProductID);
    
                //Assert
                Assert.IsFalse(isExists);
    
                //Clean up
                dbContext.Dispose();
            }
    
        }

    จากตัวอย่างด้านบน 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 นี้ได้ และดำเนินการดังนี้

    1. สร้าง generic collection สำหรับ DbSet property แต่ละตัว
    2. Config fake DbSet ใน mock framework
    3. Setup และ forward DbSet property เหล่านั้นไปที่ generic collection
      • Provider
      • Expression
      • ElementType
      • GetEnumerator()
    [TestClass]
    public class MyRepositoryTest
    {
            private DbSet<T> CreateDbSet<T>(IQueryable<T> collection) where T:class
            {
                var stubDbSet = new Mock<DbSet<T>>();
                stubDbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(collection.Provider);
                stubDbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(collection.Expression);
                stubDbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(collection.ElementType);
                stubDbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(collection.GetEnumerator());
                return stubDbSet.Object;
            }
    
            [TestMethod]
            public void list_all_available_products_from_the_data_store()
            {
                //Arrange
                var expected = new List<Product>
                {
                    new Product {ProductName ="Toyota yaris"},
                    new Product {ProductName ="Toyota altis"},
                    new Product {ProductName ="Toyota camry"}
                };
    
                var productDbSet = CreateDbSet(expected.AsQueryable());
    
                var stubContext = new Mock<MyDbContext>();
                stubContext.Setup(o=>o.Products).Returns(productDbSet);
                var rep = new MyRepository(stubContext.Object);
    
                //Act
                var actual = (List<Product>)rep.GetAll();
    
                //Assert
                CollectionAssert.AreEquivalent(expected, actual);
    
            }
    
    
            [TestMethod]
            public void return_a_product_for_given_product_id()
            {
                //Arrange
                var expected = "Toyota altis";
                var expected = new List<Product>
                {
                    new Product {ProductName ="Toyota yaris"},
                    new Product {ProductName ="Toyota altis"},
                    new Product {ProductName ="Toyota camry"}
                };
    
                var productDbSet = CreateDbSet(collection.AsQueryable());
    
                var stubContext = new Mock<MyDbContext>();
                stubContext.Setup(o => o.Products).Returns(productDbSet);
                var rep = new MyRepository(stubContext.Object);
    
                //Act
                var actual = rep.GetById(2);
    
                //Assert
                Assert.AreEqual(expected, actual.ProductName);
    
            }        
        }

    อ้างอิง : https://www.bitiniyan.com/2019/02/02/how-to-write-unit-tests-with-entity-framework-core/

  • Variables ใน Robot Framework

    วันนี้เรามาดูตัวแปร ใน Robot Framework กันดีกว่า ดู ๆ ไปตัวแปรมันก็แปลกดีนะ มาดูกันว่าเป็นไงบ้าง

    1. Case Insensitive –> ตัวพิมพ์เล็ก – พิมพ์ใหญ่เป็นตัวเดียวกัน
    2. Ignore space –> ไม่สนใจช่องว่าง
    3. Ignore underscore –> ไม่แคร์ Underscore 555

    มาดูประเภทของตัวแปรกัน ดังรูปจ้า

    1. ค่าคงที่
    2. List
    3. Dictionary หรือ Json

    ตามตัวอย่าง มารันดูข้อมูลกันจะเห็นได้ว่ามันจะรันตามลำดับ ที่เราแสดง Log to console

    ลองดูว่าถ้าเราจะให้แสดง List เฉพาะคำว่า Chotkaew จะทำยังไง ให้มองว่า Thichaluk เป็น index ที่ 0 และ Chotkaew เป็น index ที่ 1

    รันดูผลลัพธ์กัน

    มาลองดูของ dictionary กันบ้าง ให้แสดงค่าของ Thichaluk

    รันดูผลลัพธ์

    ทุกคนคงจะมองเห็นการเข้าถึงข้อมูลแต่ละประเภทกันแล้วใช่มั๊ยค่ะ

    ต่อไปมาลองสร้าง List กับ Dictionary อย่างง่าย ๆ กัน รูปแบบคำสั่งก็ไปหาดูได้ที่ https://robotframework.org ที่ Libraries –> Builtin ที่ Builtin คลิก View หา Create List กับ Create Dictionary

    รันดูผลลัพธ์

  • Should Be Equal ใน Robot Framework

    วันนี้จะมาทดลองใช้ Should Be Equal (การเปรียบเทียบ) ใน Robot framework กันค่ะ ก่อนจะถึงคำสั่งเปรียบเทียบ เราก็ต้องเขียน Test Case อื่น ๆ กันก่อน งั้นวันนี้จะเขียนแบ่ง Test Case ให้อ่านง่าย ๆ กันไปเลย เพื่อเพื่อน ๆ จะได้นำไปประยุกต์ใช้งานกันได้ค่ะ

    สิ่งที่ต้องใช้ในวันนี้ คือ Notpad++ หรือ Tool อื่น ๆ ที่เพื่อน ๆ ถนัด วันนี้เราจะใช้ Visual Studio Code กันค่ะ (เพราะเหนื่อยกับการรันผ่าน command line แล้ว) มาเริ่มกันเลยดีกว่า

    จะเห็นว่า เรามีการตั้งชื่อ Test Case ให้อ่านง่าย เพื่อจะให้รู้ว่าแต่ละขั้นเราทำอะไร ตอนเป็น Report จะได้ดูง่ายเข้าไปอีก ค่อนไปดู Report ตอนท้าย

    คำสั่งนี้จะตรวจสอบว่าค่าที่ได้ตรงกันมั๊ย จะเห็นว่าเราเขียน Test Case เป็นภาษาไทยได้นะเออ จากรูปเปรียบเทียบค่าจาก xpath ที่ locator h1 ตามคำสั่ง //h1[@class=”main-header”]  เท่ากับ “ROBOT FRAME WORK/” หรือไม่

    Locator ที่กล่าวคือตำแหน่งตามรูปข้างบน คราวนี้เราลองปรับให้ ${expect} ไม่ใช่ค่าเดียวกับ locator ที่เราอ้างถึง

    จะเห็นได้ว่าที่ log console มีการแสดงผลในการเปรียบเทียบว่าไม่เท่ากัน ไปดู Report กันซะหน่อยว่าเป็นยังไง

    Report ก็ดูง่ายมากเลยเห็นมั๊ยหล่ะ ^_^

  • ทดสอบ API ด้วย Robot Framework (Get Request)

    ก็ยังคงเขียนเกี่ยวกับ robot framework อีกนั่นแหละ ^_^ วันนี้เลยจะมาเขียนตัวอย่างการทดสอบ api ด้วย Robot Framework (Get Request) อย่างง่ายกันค่ะ

    สิ่งที่ต้องใช้

    1. API  ที่จะใช้ในการทดสอบ อันนี้จะใช้ API ที่ http://thetestingworldapi.com ค่ะ
    2. เครื่องมือที่ใช้เขียน Notepad++  ^_^
    3. Cmd

    ขั้นแรกเราไปที่ http://thetestingworldapi.com แล้วคลิกที่ API ในที่นี้ขอเลือก API ของ StudentsDetails ดังรูปค่ะ

    จากนั้นก็เปิด Notpad++ ขึ้นมาเลยค่ะ

    ที่ Settings ต้องเรียก Library  RequestsLibrary นะ แต่ก่อนอื่นต้องไปลง Library ตัวนี้กันก่อน โดยใช้คำสั่ง

    pip install robotframework-requests

    ถ้าลงแล้วก็จะตรวจสอบได้ โดยใช้คำสั่ง pip freeze ดังรูป

    มาที่ Notepad++ กันต่อ ^_^ เขียนคำสั่ง ดังนี้เลย

    จะเห็นได้ว่าเรามีแสดง status_code ออกมาด้วย มารู้จักความหมายของ status_code แต่ละตัวกันดีกว่า

    2xx  คือ OK
    3xx คือ Redirection
    4xx คือ Resource not found
    5xx คือ Server error

    มารันผลลัพธ์กันดีกว่า

    อันนี้ไม่ขอรัน code ในส่วนของ content นะ ไปรันกันเอาเอง เพราะมันเยอะมากตาลาย capture รูปมาก็คงดูไม่รู้เรื่อง ^_^

    การทดสอบ Get Request อย่างง่าย ก็ประมาณนี้นะคะ

  • การทดสอบซอฟต์แวร์ (Software Testing) – 7 ข้อมูลที่ผู้ทดสอบต้องทราบก่อนเริ่มการทดสอบซอฟต์แวร์

    บทความนี้ ไม่ได้เกี่ยวข้องกับ 7 สิ่งมหัศจรรย์ของโลกนะคะ (ก็แหงอ่าาจิ) แต่ผู้เขียนจะนำเสนอ 7 ข้อมูลที่ผู้ทดสอบต้องทราบก่อนเริ่มการทดสอบซอฟต์แวร์ (นอกเหนือจากความรู้เกี่ยวกับ Software Testing ที่ทุกท่านต้องทราบกันดีอยู่แล้ว) ซึ่งได้รวบรวมมาจากประสบการณ์ของผู้เขียนเองเผื่อจะเป็นประโยชน์สำหรับผู้ทดสอบท่านอื่น ๆ ค่ะ ตามตารางข้างล่างนี่เลยยยค่ะ

    ข้อมูลที่ผู้ทดสอบต้องทราบก่อนการทดสอบซอฟต์แวร์

    ตารางข้างต้นนั้น หวังว่าคงจะเป็นข้อมูลที่ช่วยให้ผู้ทดสอบในการเตรียมตัวทดสอบ ไม่มากก็น้อยนะคะ 🙂 ลองเอาไปปรับใช้กันดูนะคะ ยังมีข้อมูลอีกหลายส่วนเลยล่ะคะ ไปลองตั้งคำถามกับตัวเองก่อนเริ่มทดสอบดูนะคะ ว่าเราต้องทราบอะไรบ้างงงน๊าาาาา ที่จะเป็นประโยชน์ก่อนที่เราจะลงมือทดสอบซอฟต์แวร์กัน