Kullanıcı arabirimi testlerini yazma
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.
Visual Studio Code'da tümleşik terminali açın.
Microsoft deposundan adlı
selenium
bir dal indirmek için bu dala geçin ve aşağıdakigit fetch
vegit 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).İ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ı HomePageTest
arayalı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:
Diyagramda, sağlayan IWebDriver
üç yöntem gösterilir: Navigate
, FindElement
ve Close
.
Burada gösterilen üç sınıf, ChromeDriver
, FirefoxDriver
ve EdgeDriver
her biri ve yöntemlerini uygular IWebDriver
. gibi, uygulamasını da uygulayan IWebDriver
başka sınıflar SafariDriver
da 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
, FirefoxDriver
ve 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
, FirefoxDriver
ve 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:
- Özniteliğine göre
id
bağlantıyı bulun ve ardından bağlantıya tıklayın. - Sonuçta elde edilen kalıcıyı bulun.
- Kalıcıyı kapatın.
- 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.