یکشنبه , ۹ اردیبهشت ۱۴۰۳

آموزش Selenium-قسمت پنجم: اولین Selenium Webdriver Script: نمونه کد جاوا(بخش اول)

Selenium
Selenium

این قسمت به دلیل طولانی بودن و اینکه ممکن است از حوصله خواننده برای مطالعه یکباره خارج باشد، به دو بخش تقسیم شده است

سعی داریم با استفاده از کلاس “myclass” جاوا که در آموزش قبلی ایجاد کردیم، یک اسکریپت WebDriver ایجاد کنیم که:

  • صفحه Homepage تور Mercury  را واکشی کند.
  • عنوان آن را تایید کنید
  • نتایج حاصل از مقایسه را چاپ نماید
  • قبل از پایان تمام برنامه، آن را ببندد

WebDriver Code

در پایین یک کد واقعی WebDriver برای Logic ارائه شده توسط سناریوی بالا درج شده است.

نکته: با شروع به کار با فایرفاکس ۳۵، شما باید برای بهره‌برداری از Web Driver، از Gecko Driver که توسط موزیلا ایجاد شده است استفاده نمایید. Selenium 3.0 با Gecko و Firefox مشکل سازگاری(Compatibility) دارد، و تنظیم آن به شکل درست می‌تواند یک کار دشوار باشد. اگر کد کار نمی‌کند، به نسخه فایرفاکس ۴۷ یا پایین‌تر Downgrade کنید. همچنین شما می‌توانید اسکریپت‌های خود را در Chrome اجرا کنید. سلنیوم با Box برای Chrome کار می‌کند. شما فقط باید ۳ خط از کد را تغییر دهید تا اسکریپت شما با Chrome یا Firefox کار کند.

package newproject;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
//comment the above line and uncomment below line to use Chrome
//import org.openqa.selenium.chrome.ChromeDriver;
public class PG1 {

    public static void main(String[] args) {
        // declaration and instantiation of objects/variables
    	System.setProperty("webdriver.firefox.marionette","C:\\geckodriver.exe");
		WebDriver driver = new FirefoxDriver();
		//comment the above 2 lines and uncomment below 2 lines to use Chrome
		//System.setProperty("webdriver.chrome.driver","G:\\chromedriver.exe");
		//WebDriver driver = new ChromeDriver();
    	
        String baseUrl = "http://demo.guru99.com/test/newtours/";
        String expectedTitle = "Welcome: Mercury Tours";
        String actualTitle = "";

        // launch Fire fox and direct it to the Base URL
        driver.get(baseUrl);

        // get the actual value of the title
        actualTitle = driver.getTitle();

        /*
         * compare the actual title of the page with the expected one and print
         * the result as "Passed" or "Failed"
         */
        if (actualTitle.contentEquals(expectedTitle)){
            System.out.println("Test Passed!");
        } else {
            System.out.println("Test Failed");
        }
       
        //close Fire fox
        driver.close();
       
    }

}

توضیح کد

Import کردن Packageها

برای شروع، شما باید دو Package زیر را Import نمایید:

  1. *.org.openqa.selenium: حاوی کلاس WebDriver مورد نیاز برای نمونه‌سازی یک مرورگر جدید است که با یک Driver خاص بارگذاری شده است.
  2. org.openqa.selenium.firefox.FirefoxDriver: شامل کلاس FirefoxDriver مورد نیاز برای نمونه‌سازی یک Firefox-Specific Driver بر روی مرورگر نمونه‌سازی شده توسط کلاس WebDriver است.

اگر تست شما به Actionهای پیچیده‌تر مانند دسترسی به کلاس‌های دیگر، اسکرین‌شات گرفتن از مرورگر یا دستکاری فایل‌های خارجی نیاز دارد، قطعا شما نیاز به Import کردن Packageهای بیشتری خواهید داشت.

نمونه‌سازی Objectها و متغیر(Variable)

به طور معمول، این قسمت چگونگی نمونه‌سازی یک Driver Object را تشریح می‌کند.

Selenium Figure 5-1
Selenium Figure 5-1

یک کلاس FirefoxDriver بدون پارامتر به این معنی است که FireFox Profile پیشفرض توسط برنامه جاوا ما لانچ می‌شود. FireFox Profile پیشفرض مشابه لانچ کردن فایرفاکس در حالت Safe Mode است(بدون بارگذاری Extensionها).

برای راحتی کار، ما Base URL و عنوان مورد انتظار را به عنوان متغیر ذخیره کردیم.

لانچ یک Browser Session

متد ()get در WebDriver برای لانچ یک Browser Session جدید استفاده شده و آنرا به URLای که شما به عنوان پارامتر آن مشخص کرده‌اید، هدایت می کند.

Selenium Figure 5-2
Selenium Figure 5-2

عنوان واقعی page را دریافت کنید

کلاس WebDriver متدی به نام ()getTitle دارد که همیشه برای بدست آوردن عنوان صفحه‌ای که در حال حاضر بارگذاری شده است، استفاده می‌شود.

Selenium Figure 5-3
Selenium Figure 5-3

مقادیر مورد انتظار(Expected) و واقعی(Actual) را مقایسه کنید

این قسمت از کد برای مقایسه عنوان واقعی(Actual Title) با مورد انتظار(Expected Title)، به سادگی از یک ساختار if-else در Basic Java استفاده می‌کند.

Selenium Figure 5-4
Selenium Figure 5-4

پایان دادن(Terminating) به یک Browser Session

متد “()close”برای بستن پنجره مرورگر استفاده می‌شود.

Selenium Figure 5-5
Selenium Figure 5-5

پایان دادن(Terminating) به تمام برنامه

اگر شما از این Command بدون بستن تمام پنجره‌های مرورگر استفاده می‌کنید، تمام برنامه‌ جاوایی به پایان خواهد رسید در حالی که پنجره مرورگر را به صورت باز رها می‌کند.

Selenium Figure 5-6
Selenium Figure 5-6

اجرا کردن تست

دو راه برای اجرای کد در Eclipse IDE وجود دارد:

  1. در نوار منوی Eclipse، روی Run>Run کلیک کنید.
  2. Ctrl+F11 را فشار دهید تا کل کد را اجرا کنید.
Selenium Figure 5-7
Selenium Figure 5-7

اگر همه چیز را به درستی انجام دهید، Eclipse این خروجی را به شما ارائه می‌دهد: “!Test Passed”

Selenium Figure 5-8
Selenium Figure 5-8

موقعیت‌یابی عناصر GUI

موقعیت‌یابی عناصر در WebDriver با استفاده از متد “(()findElement(By.locator” انجام می‌‍شود. قسمت “Locator” از کد مانند دیگر Locatorهاییست که در Selenium IDE هم استفاده می‌شود. اما با توجه به اینکه ما بحث در مورد WebDriver را زودتر آغاز کردیم، موضوع Locatorها در Selenium IDE بعدا مورد بحث واقع خواهد شد. در این زمینه توصیه می‌کنم، که عناصر GUI را با استفاده از IDE موقعیت‌یابی کرده و هنگامی که شناسایی عناصر با موفقیت انجام شد، کد را به WebDriver، اکسپورت نمایید.

در اینجا یک نمونه کد از یک عنصر که با استفاده از ID آن موقعیت‌یابی می‌شود، ارائه شده است. در اینجا Facebook به عنوان Base URL استفاده شده است.

package newproject;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class PG2 {
    public static void main(String[] args) {
    	System.setProperty("webdriver.firefox.marionette","C:\\geckodriver.exe");
    	WebDriver driver = new FirefoxDriver();
        String baseUrl = "http://www.facebook.com";
        String tagName = "";
        
        driver.get(baseUrl);
        tagName = driver.findElement(By.id("email")).getTagName();
        System.out.println(tagName);
        driver.close();
        System.exit(0);
}
}

ما از متد ()getTagName برای استخراج Tag Name آن عنصر خاص که ID آن “ایمیل” است استفاده کردیم. هنگام اجرا، این کد باید بتواند Tag Name “ورودی” را به درستی شناسایی کرده و آن را در پنجره کنسول Eclipse چاپ کند.

Selenium Figure 5-9
Selenium Figure 5-9

خلاصه مطالب برای موقعیت‌یابی عناصر

Variation

شرح

مثال

By.className

عناصر را بر اساس مقدار Attribute(ویژگی) "Class" می‌یابد

findElement(By.className("someClassName"))

By.cssSelector

عناصر را بر اساس Driverای که ذیل موتور انتخابگر CSS است پیدا می‌کند

findElement(By.cssSelector("input#email"))

By.id

عناصر را بوسیله مقدار Atrribut(ویژگی) "id" را موقعیت‌یابی می‌نماید

findElement(By.id("someId"))

By.linkText

Link Elementها را بوسیله متن دقیقی که آن نشان می‌دهد، می‌یابد

findElement(By.linkText("REGISTRATION"))

By.name

عناصر را بوسیله مقدار Atrribut(ویژگی) "name" را موقعیت‌یابی می‌نماید

findElement(By.name("someName"))

By.partialLinkText

عناصر حاوی متن لینک(Link Text) داده شده را موقعیت‌یابی می‌کند

findElement(By.partialLinkText("REG"))

By.tagName

عناصر را بوسیله Tag Name آنها موقعیت‌یابی می‌کند

findElement(By.tagName("div"))

By.xpath

عناصر را از طریق XPath می‌کند

findElement(By.xpath("//html/body/div/table/tbody/
tr/td[2]/table/ tbody/tr[4]/td/table/
tbody/tr/td[2]/table/tbody/tr[2]/td[3]/
form/table/tbody/tr[5]"))

یک نکته در استفاده از (()findElement(By.cssSelector

()By.cssSelector از امکان “contains” پشتیبانی نمی‌کند. کد Selenium IDE را در پایین در نظر بگیرید:

Selenium Figure 5-10
Selenium Figure 5-10

در Selenium IDE(مذکور در بالا)، کل تست پاس شد. با این حال در اسکریپت WebDriver پایین، همان تست یک خطا ایجاد کرد. چرا که WebDriver از کلیدواژه “contains” در زمان استفاده در متد ()By.cssSelector پشتیبانی نمی‌کند.

Selenium Figure 5-11
Selenium Figure 5-11

دستورات(Command) مشترک

نمونه‌سازی عناصر وب

به جای استفاده هر باره از سینتکس طولانی “(()driver.findElement(By.locator” که با استفاده از آن به یک عنصر خاص دسترسی پیدا می‌کنید، می‌توانیم یک شیء WebElement را برای آن نمونه‌سازی کنیم. کلاس WebElement در بسته”*.org.openqa.selenium” قرار دارد.

Selenium Figure 5-12
Selenium Figure 5-12

کلیک بر روی یک عنصر

احتمالا کلیک کردن شایع‌ترین روش تعامل با عناصر وب است. متد ()click برای شبیه‌سازی کلیک روی هر عنصر استفاده می‌شود. مثال زیر نشان می‌دهد که چگونه از ()click برای کلیک  روی دکمه “Sign-in” سیستم Mercury Tour استفاده می‌شود.

Selenium Figure 5-13
Selenium Figure 5-13

هنگام استفاده از متد ()click باید به موارد زیر توجه داشته باشید:

  • این متد هیچ پارامتر/آرگومانی را نمی‌پذیرد.
  • این متد در صورت لزوم به طور خودکار برای بارگذاری یک صفحه جدید منتظر می‌ماند.
  • عنصری که روی آن کلیک می‌شود، باید قابل مشاهده باشد‌(یعنی ارتفاع و عرض نباید برابر با صفر باشد).

دستورات Get

دستورات Get اطلاعات مهم مختلفی را در مورد صفحه/عنصر واکشی می‌کنند. در اینجا برخی از دستورات مهم “Get” ارائه شده است که شما باید با آنها آشنا باشید:

دستور

شرح

get()

* به صورت اتوماتیک یک پنجره مرورگر جدید باز کرده و صفحه‌ای را که شما درون پرانتز مشخص کرده‌اید را واکشی می‌کند
* این دستور همتای دستور "open" در Selenium IDE است
* این پارامتر باید یک String Object باشد

getTitle()

* نیازی به پارامتر ندارد
* عنوان صفحه جاری را واکشی می‌کند
* فضاهای سفید Trim شده را برجسته و پیگیری می‌کند
* در صورتیکه صفحه فاقد عنوان باشد یک Null String را Return می‌کند

getPageSource()

* نیازی به پارامتر ندارد
* Source Code مربوط به صفحه را به صورت یک مقدار رشته‌ای Return می‌کند

getCurrentUrl()

* نیازی به پارامتر ندارد
* رشته قابل نمایش URL جاری که به مرورگر بدان نگاه می‌کند را واکشی می‌نماید

getText()

* Inner Text مربوط به عنصری که شما مشخص کرده‌اید را واکشی می‌کند

دستورات Navigate

این دستورات به شما امکان می‌دهند تا روی صفحات وب رفرش انجام داده، و یا به سمت آنها هدایت شده و یا میان صفحات مختلف وب جلو و عقب بروید.

دستور

شرح

navigate().to()

* این دستور به صورت اتوماتیک یک پنجره مرورگر جدید باز کرده و صفحه‌ای را که شما در پرانتز آن مشخص کرده‌اید را باز می‌کند
* دقیقا همان چیزی را انجام می‌دهد که متد ()get انجام می‌دهد

navigate().refresh()

* نیازی به پارامتر ندارد
* صفحه جاری را رفرش می‌کند

navigate().back()

* نیازی به پارامتر ندارد
* شما را بوسیله یک صفحه در مرورگر به عقب باز می‌گرداند

navigate().forward()

* نیازی به پارامتر ندارد
* شما را بوسیله یک صفحه در مرورگر به جلو می‌برد

بستن و ترک مرورگر ویندوز

دستور

شرح

close()

* نیازی به پارامتر ندارد
* فقط پنجره مرورگری که WebDriver در حال حاضر آنرا کنترل می‌کند را می‌بندد

quit()

* نیازی به پارامتر ندارد
* تمام پنجره‌هایی که WebDriver باز کرده است را می‌بندد

Selenium Figure 5-14
Selenium Figure 5-14

برای اینکه تفاوت میان ()close و ()quit به وضوح مشخص شود، سعی کنید کد زیر را اجرا کنید. این کد از یک صفحه وب استفاده می‌کند که به طور خودکار به محض بارگذاری صفحه، پنجره‌ای را به صورت پاپ آپ ارائه می‌دهد، و پس از خروج، پنجره دیگری را باز می‌کند.

Selenium Figure 5-15
Selenium Figure 5-15

توجه داشته باشید که تنها پنجره مرورگر والد(Parent) بسته شده است و نه دو پنجره پاپ آپ.

Selenium Figure 5-16
Selenium Figure 5-16

اما اگر شما از ()quit استفاده کنید، نه تنها والد  بلکه تمام پنجره‌ها بسته خواهند شد. سعی کنید کد زیر را اجرا کنید. با اجرای این کد متوجه خواهید شد که دو پنجره بالا نیز به طور خودکار بسته خواهند شد.

package newproject;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class PG3 {
    public static void main(String[] args) {
    	System.setProperty("webdriver.firefox.marionette","C:\\geckodriver.exe");
    	WebDriver driver = new FirefoxDriver();
        driver.get("http://www.popuptest.com/popuptest2.html");
        driver.quit();  // using QUIT all windows will close
    }
}

سوییچ کردن بین فریم‌ها

برای دسترسی به عناصر GUI در Frame، ما ابتدا باید WebDriver را برای تمرکز بر پنجره فریم یا پاپ آپ اولویت‌بندی کنیم تا بتوانیم به عناصر درون آنها دسترسی پیدا کنیم.

Selenium Figure 5-17
Selenium Figure 5-17

این صفحه دارای ۳ فریم است که Attribute(ویژگی) “name” آنها در بالا نشان داده شده است. ما مایل به دسترسی به لینک “Deprecated”(منسوخ شده) هستیم که در بالا دور آنرا با رنگ زرد خط کشیده‌ایم. برای انجام این کار، ابتدا باید به WebDriver دستور بدهیم تا با استفاده از متد “()switchTo().frame”، به فریم “classFrame” سوییچ کنیم. ما از ویژگی name مربوط به فریم به عنوان پارامتر برای قسمت “()frame” استفاده خواهیم کرد.

package newproject;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class PG4 {
	  public static void main(String[] args) {
		  	System.setProperty("webdriver.firefox.marionette","C:\\geckodriver.exe");  
		  	WebDriver driver = new FirefoxDriver();
	        driver.get("http://demo.guru99.com/selenium/deprecated.html");
	        driver.switchTo().frame("classFrame");
	        driver.findElement(By.linkText("Deprecated")).click();
	        driver.close(); 
	    }
}

پس از اجرای این کد، خواهید دید که فریم “classFrame” برای صفحه “Deprecated API” اخذ شده است، به این معنی که کد ما با موفقیت قادر به دسترسی به لینک “Deprecated” خواهد بود.

این یک آموزش طولانی مدت است. بنابراین قسمت‌های بعدی به محض آماده شدن علاوه بر اینکه در صفحه Home وبسایت اطلاعرسانی خواهد شد، به صورت دسته‌بندی شده از اینجا نیز در دسترس است.

ابوالفضل خواجه دیزجی

همچنین ببینید

Selenium

آموزش Selenium-قسمت هفدهم: Mouse Click Event و Keyboard Event و موضوع Action Class در Selenium WebDriver

در این بخش، ما رویداد کیبورد(Keyboard Event) و ماوس(Mouse Event) را در Selenium Webdriver آموزش …

۳ دیدگاه

  1. سلام و وقت بخیر
    پس از اجرای اولین تکه کد ، با پیغام زیر مواجه می شوم:

    Error: Unable to initialize main class NP.NC
    Caused by: java.lang.NoClassDefFoundError: org/openqa/selenium/WebDriver

    لطفا راهنمایی بفرمائید.

  2. باسلام

    پیشنهاد می شود یک قسمت برای ارائه پرسش و پاسخ در هر آموزش ایجاد شود تا هم آموزش کاربردی تر باشد و هم از تجربیات یکدیگر استفاده نماییم

    باسپاس

    • ابوالفضل خواجه دیزجی
      ابوالفضل خواجه دیزجی

      سلام خدمت شما دوست عزیز تیستنی
      به صورت معمول در اکثر سایت‌ها(یا لااقل چیزی که بنده رویت کردم)، پرسش و پاسخ در قالب کامنت‌ ثبت میشه.
      معهذا اگر برای هر کدام از دوستان در بخشی سوالی پیش آمد، میتونند در همان صفحه‌ای که پرسش از همون جا براشون شروع شده، سوال رو در قالب کامنت مطرح کنند.
      ان شا ا… نویسندگان مربوطه پاسخ شما رو به صورت کامنت دیگری درج خواهند کرد.
      اما یکی از نکاتی که باید طرح کنم این هست که احتمالا این پرسش‌ها در بخش آموزش بیشتر مطرح میشه. یکی از مهمترین علل بروز چنین پرسش‌هایی این هست، که غالب آموزش‌ها هنوز تکمیل نشدن، و اگر اونها به یک تکامل مناسب برسن، بسیاری از پرسش‌ها خود به خود پاسخ داده خواهد شد.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *