Kullanıcı arabirimi testlerini yazma

Tamamlandı

Bu bölümde, Andy ve Amita'nın Amita'nın tanımladığı kullanıcı arabirimi davranışlarını doğrulayan Selenium testleri yazmasına yardımcı olursunuz.

Amita normalde Chrome, Firefox ve Microsoft Edge üzerinde testler çalıştırır. Burada, sen de aynısını yap. Kullanacağınız Microsoft tarafından barındırılan aracı, bu tarayıcıların her biriyle çalışacak şekilde önceden yapılandırılmıştır.

GitHub'dan dalı getirme

Bu bölümde, dalı selenium GitHub'dan getirebilirsiniz. Ardından bu dala göz atabilirsiniz veya bu dala geçiş yapabilirsiniz. Dalın içeriği, Andy ve Amita'nın yazdığı testlerle birlikte izlemenize yardımcı olacaktır.

Bu dal, önceki modüllerde birlikte çalıştığınız Space Game projesini içerir. Ayrıca başlangıç olarak bir Azure Pipelines yapılandırması içerir.

  1. Visual Studio Code'da tümleşik terminali açın.

  2. Microsoft deposundan adlı selenium bir dal indirmek için bu dala geçin ve aşağıdaki git fetch ve git checkout komutlarını çalıştırın:

    git fetch upstream selenium
    git checkout -B selenium upstream/selenium
    

    Bahşiş

    Önceki ünitede Amita'nın el ile testini takip ettiyseniz, bu komutları zaten çalıştırmış olabilirsiniz. Bunları önceki ünitede zaten çalıştırdıysanız, yine de şimdi yeniden çalıştırabilirsiniz.

    Yukarı akışın Microsoft GitHub deposuna başvurduğunu hatırlayın. Projenizin Git yapılandırması, bu ilişkiyi ayarladığınız için yukarı akış uzak değerini anlar. Projeyi Microsoft deposundan çatallayıp yerel olarak kopyaladığınızda ayarladınız.

    Kısacası bu dalı GitHub deposuna göndereceksiniz (origin olarak bilinir).

  3. İsteğe bağlı olarak Visual Studio Code'da azure-pipelines.yml dosyasını açın. İlk yapılandırma hakkında bilgi sahibi olun.

    Yapılandırma, bu öğrenme yolundaki önceki modüllerde oluşturduğunuz yapılandırmaya benzer. Yalnızca uygulamanın Sürüm yapılandırmasını derler. Kısa olması için, önceki modüllerde ayarladığınız tetikleyicileri, el ile onayları ve testleri de atlar.

    Dekont

    Daha sağlam bir yapılandırma, derleme işlemine katılan dalları belirtebilir. Örneğin, kod kalitesini doğrulamaya yardımcı olmak için herhangi bir dalda her değişiklik gönderişiniz için birim testleri çalıştırabilirsiniz. Uygulamayı daha kapsamlı test gerçekleştiren bir ortama da dağıtabilirsiniz. Ancak bu dağıtımı yalnızca çekme isteğiniz olduğunda, yayın adayınız olduğunda veya kodu main ile birleştirdiğinizde yaparsınız.

    Daha fazla bilgi için bkz . Git ve GitHub kullanarak derleme işlem hattınıza kod iş akışı uygulama ve İşlem hattı tetikleyicilerini derleme.

Birim testi kodunu yazma

Amita, web tarayıcısını denetleen kod yazmayı öğrenmek için heyecanlanmıştır.

O ve Andy Selenium testlerini yazmak için birlikte çalışacaklar. Andy zaten boş bir NUnit projesi ayarladı. Süreç boyunca Selenium belgelerine, birkaç çevrimiçi öğreticiye ve Amita testleri el ile yaparken aldıkları notlara başvururlar. Bu modülün sonunda, süreci atlatmanıza yardımcı olacak daha fazla kaynak bulacaksınız.

Şimdi Andy ve Amita'nın testlerini yazmak için kullandığı süreci gözden geçirelim. Bunu, Visual Studio Code'daki Tailspin.SpaceGame.Web.UITests dizininde HomePageTest.cs dosyasını açarak izleyebilirsiniz.

HomePageTest sınıfını tanımlama

Andy: yapmamız gereken ilk şey test sınıfımızı tanımlamaktır. Birkaç adlandırma kuralından birini izlemeyi seçebiliriz. Sınıfımızı HomePageTestarayalım. Bu sınıfta, giriş sayfasıyla ilgili tüm testlerimizi koyacağız.

Andy bu kodu HomePageTest.cs dosyasına ekler:

public class HomePageTest
{
}

Andy: NUnit çerçevesi için kullanılabilir olması için bu sınıfı olarak public işaretlememiz gerekir.

IWebDriver üye değişkenini ekleme

Andy: Şimdi bir IWebDriver üye değişkenine ihtiyacımız var. IWebDriver , bir web tarayıcısı başlatmak ve web sayfası içeriğiyle etkileşime geçmek için kullandığınız programlama arabirimidir.

Programlamadaki arabirimleri duymuştum. Bana biraz daha anlatabilir misin?

Andy: Arabirimi, bir bileşenin nasıl davranması gerektiğine ilişkin bir belirtim veya şema olarak düşünün. Arabirim, bu bileşenin yöntemlerini veya davranışlarını sağlar. Ancak arabirim, temel alınan ayrıntıları sağlamaz. Siz veya başka biri bu arabirimi uygulayan bir veya daha fazla somut sınıf oluşturabilirsiniz. Selenium ihtiyacımız olan somut sınıfları sağlar.

Bu diyagramda IWebDriver arabirimi ve bu arabirimi uygulayan sınıflardan birkaçı gösterilir:

Diagram of the IWebDriver interface, its methods, and concrete classes.

Diyagramda, sağlayan IWebDriver üç yöntem gösterilir: Navigate, FindElementve Close.

Burada gösterilen üç sınıf, ChromeDriver, FirefoxDriverve EdgeDriverher biri ve yöntemlerini uygular IWebDriver . gibi, uygulamasını da uygulayan IWebDriverbaşka sınıflar SafariDriverda vardır. Her sürücü sınıfı, temsil ettiği web tarayıcısını denetleyebilir.

Andy sınıfına HomePageTest şu kod gibi adlı driver bir üye değişkeni ekler:

public class HomePageTest
{
    private IWebDriver driver;
}

Test fikstürlerini tanımlama

Andy: Chrome, Firefox ve Edge'de tüm testleri çalıştırmak istiyoruz. NUnit'de, test etmek istediğimiz her tarayıcı için bir kez olmak üzere tüm test kümesini birden çok kez çalıştırmak için test fikstürlerini kullanabiliriz.

NUnit'de, test fikstürlerinizi tanımlamak için özniteliğini TestFixture kullanırsınız. Andy bu üç test armatürlerini sınıfına HomePageTest ekler:

[TestFixture("Chrome")]
[TestFixture("Firefox")]
[TestFixture("Edge")]
public class HomePageTest
{
    private IWebDriver driver;
}

Andy: Şimdi test sınıfımız için bir oluşturucu tanımlamamız gerekiyor. Oluşturucu, NUnit bu sınıfın bir örneğini oluşturduğunda çağrılır. Oluşturucu, bağımsız değişkeni olarak test armatürlerimize bağladığımız dizeyi alır. Kod şöyle görünür:

[TestFixture("Chrome")]
[TestFixture("Firefox")]
[TestFixture("Edge")]
public class HomePageTest
{
    private string browser;
    private IWebDriver driver;

    public HomePageTest(string browser)
    {
        this.browser = browser;
    }
}

Andy: Kurulum kodumuzda geçerli tarayıcı adını kullanabilmek için üye değişkenini ekledik browser . Şimdi kurulum kodunu yazalım.

Kurulum yöntemini tanımlama

Andy: Ardından, üye değişkenimizi IWebDriver test ettiğimiz tarayıcı için bu arabirimi uygulayan bir sınıf örneğine atamamız gerekir. ChromeDriver, FirefoxDriverve EdgeDriver sınıfları sırasıyla Chrome, Firefox ve Edge için bu arabirimi uygular.

Şimdi değişkeni ayarlayan driver adlı Setup bir yöntem oluşturalım. NUnit'e OneTimeSetUp test fikstür başına bir kez bu yöntemi çalıştırmasını söylemek için özniteliğini kullanırız.

[OneTimeSetUp]
public void Setup()
{
}

yöntemindeSetup, üye değişkenini driver tarayıcı adına göre uygun somut uygulamaya atamak için deyimini switch kullanabiliriz. Şimdi bu kodu ekleyelim.

// Create the driver for the current browser.
switch(browser)
{
    case "Chrome":
    driver = new ChromeDriver(
        Environment.GetEnvironmentVariable("ChromeWebDriver")
    );
    break;
    case "Firefox":
    driver = new FirefoxDriver(
        Environment.GetEnvironmentVariable("GeckoWebDriver")
    );
    break;
    case "Edge":
    driver = new EdgeDriver(
        Environment.GetEnvironmentVariable("EdgeWebDriver"),
        new EdgeOptions
        {
            UseChromium = true
        }
    );
    break;
    default:
    throw new ArgumentException($"'{browser}': Unknown browser");
}

Her sürücü sınıfı için oluşturucu, Selenium'un web tarayıcısını denetlemesi için ihtiyaç duyduğu sürücü yazılımının isteğe bağlı bir yolunu izler. Daha sonra burada gösterilen ortam değişkenlerinin rolünü ele alacağız.

Bu örnekte oluşturucu ayrıca Edge'in EdgeDriver Chromium sürümünü kullanmak istediğimizi belirtmek için ek seçenekler gerektirir.

Yardımcı yöntemleri tanımlama

Testler boyunca iki eylemi tekrarlamamız gerektiğini biliyorum:

  • Tıkladığımız bağlantılar ve görünmesini beklediğimiz kalıcı pencereler gibi sayfadaki öğeleri bulma
  • Sayfada kalıcı pencerelerin gösterildiği bağlantılar ve her bir kalıcı pencereyi kapatan düğme gibi öğelere tıklama

Şimdi her eylem için birer tane olmak üzere iki yardımcı yöntem yazalım. Sayfada bir öğe bulan yöntemiyle başlayacağız.

FindElement yardımcı yöntemini yazma

Sayfada bir öğeyi bulursanız, bu genellikle sayfa yükleme veya kullanıcı bilgi girme gibi başka bir olaya yanıt olarak olur. Selenium, bir koşulun WebDriverWait doğru olmasını beklemenizi sağlayan sınıfını sağlar. Belirtilen süre içinde koşul doğru değilse, WebDriverWait bir özel durum veya hata oluşturur. Sınıfını WebDriverWait , belirli bir öğenin görüntülenmesini beklemek ve kullanıcı girişi almaya hazır olmak için kullanabiliriz.

Sayfadaki bir öğeyi bulmak için sınıfını By kullanın. sınıfı By , bir öğeyi adına, CSS sınıf adına, HTML etiketine veya bizim örneğimizde özniteliğine göre bulmanıza id olanak sağlayan yöntemler sağlar.

Andy ve Amita yardımcı yöntemini kodlar FindElement . Şu koda benzer:

private IWebElement FindElement(By locator, IWebElement parent = null, int timeoutSeconds = 10)
{
    // WebDriverWait enables us to wait for the specified condition to be true
    // within a given time period.
    return new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutSeconds))
        .Until(c => {
            IWebElement element = null;
            // If a parent was provided, find its child element.
            if (parent != null)
            {
                element = parent.FindElement(locator);
            }
            // Otherwise, locate the element from the root of the DOM.
            else
            {
                element = driver.FindElement(locator);
            }
            // Return true after the element is displayed and is able to receive user input.
            return (element != null && element.Displayed && element.Enabled) ? element : null;
        });
}

ClickElement yardımcı yöntemini yazma

Andy: Şimdi bağlantılara tıklayan bir yardımcı yöntemi yazalım. Selenium, bu yöntemi yazmak için birkaç yol sağlar. Bunlardan biri arabirimdir IJavaScriptExecutor . Bununla, JavaScript kullanarak program aracılığıyla bağlantılara tıklayabiliriz. Bu yaklaşım düzgün çalışır çünkü bağlantıları önce görünüme kaydırmadan tıklatabilir.

ChromeDriver, FirefoxDriverve EdgeDriver her uygulama IJavaScriptExecutor. Sürücüyü bu arabirime atamamız ve ardından temel alınan HTML nesnesinde JavaScript click() yöntemini çalıştırmak için çağrısı ExecuteScript yapmamız gerekir.

Andy ve Amita yardımcı yöntemini kodlar ClickElement . Şu koda benzer:

private void ClickElement(IWebElement element)
{
    // We expect the driver to implement IJavaScriptExecutor.
    // IJavaScriptExecutor enables us to execute JavaScript code during the tests.
    IJavaScriptExecutor js = driver as IJavaScriptExecutor;

    // Through JavaScript, run the click() method on the underlying HTML object.
    js.ExecuteScript("arguments[0].click();", element);
}

Amita: Bu yardımcı yöntemleri ekleme fikrini seviyorum. Neredeyse tüm testlerde kullanılacak kadar genel görünüyorlar. Daha sonra ihtiyaç duyduğunuzda daha fazla yardımcı yöntem ekleyebiliriz.

Test yöntemini tanımlama

Andy: Artık test yöntemini tanımlamaya hazırız. Daha önce çalıştırdığımız el ile gerçekleştirilen testlere dayanarak bu yöntemi ClickLinkById_ShouldDisplayModalByIdçağıralım. Test yöntemlerine testin tam olarak neyi başardığını tanımlayan açıklayıcı adlar vermek iyi bir uygulamadır. Burada, özniteliği tarafından id tanımlanan bir bağlantıya tıklamak istiyoruz. Ardından, özniteliğini kullanarak id da uygun kalıcı pencerenin göründüğünü doğrulamak istiyoruz.

Andy, test yöntemi için başlangıç kodu ekler:

public void ClickLinkById_ShouldDisplayModalById(string linkId, string modalId)
{
}

Andy: Daha fazla kod eklemeden önce bu testin ne yapacağını tanımlayalım.

Bu kısmı ben halledebilirim. Yapmak istediğimiz:

  1. Özniteliğine göre id bağlantıyı bulun ve ardından bağlantıya tıklayın.
  2. Sonuçta elde edilen kalıcıyı bulun.
  3. Kalıcıyı kapatın.
  4. Kalıcının başarıyla görüntülendiğini doğrulayın.

Andy: Harika. Ayrıca birkaç şeyi daha halletmemiz gerekecek. Örneğin, sürücü yüklenemediyse testi yoksaymalıyız ve yalnızca kalıcı görüntülendiğinde kalıcıyı kapatmamız gerekir.

Kahve bardaklarını yeniden doldurduktan sonra Andy ve Amita, test yöntemlerine kod ekler. Sayfa öğelerini bulmak ve bağlantılar ile düğmelere tıklamak için yazdıkları yardımcı yöntemleri kullanırlar. Sonuç şu şekildedir:

public void ClickLinkById_ShouldDisplayModalById(string linkId, string modalId)
{
    // Skip the test if the driver could not be loaded.
    // This happens when the underlying browser is not installed.
    if (driver == null)
    {
        Assert.Ignore();
        return;
    }

    // Locate the link by its ID and then click the link.
    ClickElement(FindElement(By.Id(linkId)));

    // Locate the resulting modal.
    IWebElement modal = FindElement(By.Id(modalId));

    // Record whether the modal was successfully displayed.
    bool modalWasDisplayed = (modal != null && modal.Displayed);

    // Close the modal if it was displayed.
    if (modalWasDisplayed)
    {
        // Click the close button that's part of the modal.
        ClickElement(FindElement(By.ClassName("close"), modal));

        // Wait for the modal to close and for the main page to again be clickable.
        FindElement(By.TagName("body"));
    }

    // Assert that the modal was displayed successfully.
    // If it wasn't, this test will be recorded as failed.
    Assert.That(modalWasDisplayed, Is.True);
}

Amita: Kodlama şu ana kadar harika görünüyor. Ancak bu testi id daha önce topladığımız özniteliklere nasıl bağlayabiliriz?

Harika bir soru. Bunu bir sonraki adımda hallederiz.

Test çalışması verilerini tanımlama

Andy: NUnit'te testlerinize birkaç yolla veri sağlayabilirsiniz. Burada özniteliğini TestCase kullanırız. Bu öznitelik, daha sonra çalıştırıldığında test yöntemine geri geçiş yaptığı bağımsız değişkenleri alır. Her birinin uygulamamızın farklı bir özelliğini test eden birden çok TestCase özniteliğimiz olabilir. Her TestCase öznitelik, işlem hattı çalıştırmasının sonunda görüntülenen rapora dahil edilen bir test çalışması oluşturur.

Andy bu TestCase öznitelikleri test yöntemine ekler. Bu öznitelikler Oyun indir düğmesini, oyun ekranlarından birini ve puan tablosundaki en iyi oyuncuyu açıklar. Her öznitelik iki id öznitelik belirtir: biri tıkılacak bağlantı için, diğeri de ilgili kalıcı pencere için.

// Download game
[TestCase("download-btn", "pretend-modal")]
// Screen image
[TestCase("screen-01", "screen-modal")]
// // Top player on the leaderboard
[TestCase("profile-1", "profile-modal-1")]
public void ClickLinkById_ShouldDisplayModalById(string linkId, string modalId)
{

...

Andy: Her TestCase öznitelik için ilk parametre, tıkılacak bağlantının özniteliğidir id . İkinci parametre, görünmesini beklediğimiz kalıcı pencerenin özniteliğidir id . Bu parametrelerin test yöntemimizdeki iki dizeli bağımsız değişkenlere nasıl karşılık olduğunu görebilirsiniz.

Bunu görüyorum. Biraz pratikle, kendi testlerimi ekleyebilirim. Bu testlerin işlem hattımızda ne zaman çalıştığını görebiliriz?

Andy: Değişiklikleri işlem hattı üzerinden göndermeden önce kodun yerel olarak derlendiğini ve çalıştığını doğrulayalım. Değişiklikleri işleyip GitHub'a göndereceğiz ve yalnızca her şeyin çalıştığını doğruladıktan sonra işlem hattında ilerlemelerini sağlayacağız. Şimdi testleri yerel olarak çalıştıralım.