الانتظار الضمني والصريح Selenium مع بناء الجملة
⚡ ملخص ذكي
Selenium تُزامن أوامر الانتظار نصوص التشغيل الآلي مع سلوك الصفحة الديناميكي، مما يمنع فشل الاختبارات الناتج عن العناصر التي يتم تحميلها بشكل غير متزامن. يشرح هذا المرجع استراتيجيات الانتظار الضمني والصريح والمرن باستخدام صيغة WebDriver، وكيفية عملها. Java نماذج برمجية، وإرشادات عملية حول اختيار وقت الانتظار المناسب لتنفيذ اختبار مستقر وموثوق.

In Seleniumتلعب أوامر الانتظار دورًا هامًا في تنفيذ اختبارات موثوقة. في هذا الدرس، ستتعرف على الجوانب الرئيسية والاختلافات بين أوامر الانتظار الضمنية والصريحة. Seleniumبالإضافة إلى الاستخدام العملي لـ Fluent Wait.
لماذا نحتاج إلى الانتظار Selenium?
يتم تطوير معظم تطبيقات الويب الحديثة باستخدام اياكس و Javaسيناريوعندما يقوم المتصفح بتحميل صفحة، قد يتم تحميل العناصر التي نريد التفاعل معها على فترات زمنية مختلفة.
لا يقتصر الأمر على صعوبة تحديد العنصر فحسب، بل إذا لم يتم تحديد موقع العنصر في الوقت المناسب، Selenium سوف يرمي ElementNotVisibleException. Selenium تعمل خاصية الانتظار على حل مشكلة التزامن هذه من خلال منح برنامج تشغيل الويب نافذة محددة للعثور على عنصر قبل الفشل.
لنفترض سيناريو يتم فيه استخدام كل من الانتظار الضمني والانتظار الصريح في نفس الاختبار. افترض أن مدة الانتظار الضمني مضبوطة على 20 ثانية، ومدة الانتظار الصريح مضبوطة على 10 ثوانٍ.
إذا كنا نبحث عن عنصر يخضع لشروط معينة الشروط المتوقعة (انتظار صريح) وإذا لم يكن العنصر موجودًا ضمن النافذة الصريحة البالغة 10 ثوانٍ، فإن WebDriver يعود إلى النافذة الضمنية البالغة 20 ثانية قبل طرح استثناء. ElementNotVisibleException.
Selenium انتظار WebDriver
- الانتظار الضمني
- الانتظار الصريح
- الانتظار بطلاقة
الانتظار الضمني Selenium
استخدم الانتظار الضمني Selenium يُوجّه هذا الإعداد برنامج تشغيل الويب (WebDriver) للانتظار لمدة زمنية محددة قبل إطلاق استثناء NoSuchElementException. القيمة الافتراضية هي 0. بعد ضبط الإعداد، يقوم برنامج تشغيل الويب باستطلاع DOM خلال تلك المدة قبل أن يتوقف. Selenium استعار WebDriver مفهوم الانتظار الضمني من Watir.
في المثال أدناه، نُعلن عن انتظار ضمني لمدة 10 ثوانٍ. إذا لم يكن العنصر موجودًا خلال هذه المدة، فسيتم طرح استثناء.
صيغة الانتظار الضمني (Selenium 4):
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
package guru.test99;
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;
public class AppTest {
protected WebDriver driver;
@Test
public void guru99tutorials() throws InterruptedException {
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
String eTitle = "Demo Guru99 Page";
String aTitle = "";
// launch Chrome and redirect it to the Base URL
driver.get("https://demo.guru99.com/test/guru99home/");
// Maximize the browser window
driver.manage().window().maximize();
// get the actual value of the title
aTitle = driver.getTitle();
// compare the actual title with the expected title
if (aTitle.equals(eTitle)) {
System.out.println("Test Passed");
} else {
System.out.println("Test Failed");
}
// close browser
driver.close();
}
}
شرح Code
في المثال أعلاه، ضع في اعتبارك العبارة التالية:
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
Selenium استبدل الإصدار 4 التوقيع القديم ذي الوسيطين (عدد صحيح بالإضافة إلى وحدة زمنية) بوسيط واحد من نوع Duration. يدعم صنف Duration الثواني والدقائق والمللي ثانية ووحدات زمنية أخرى من خلال دوال مساعدة ثابتة مثل Duration.ofSeconds وDuration.ofMillis وDuration.ofMinutes.
صريح انتظر Selenium
استخدم صريح انتظر Selenium يُوجّه هذا الأمر برنامج تشغيل الويب (WebDriver) للانتظار حتى استيفاء شروط مُحددة (الشروط المتوقعة) أو لمدة زمنية قصوى قبل إطلاق استثناء ElementNotVisibleException. يُعدّ هذا الانتظار أكثر ذكاءً لأنه ينطبق فقط على العنصر المُحدد. يُفضّل استخدام الانتظار الصريح على الانتظار الضمني عندما يتطلب الاختبار التعامل مع محتوى Ajax مُحمّل ديناميكيًا.
بمجرد الإعلان عن انتظار صريح، يجب عليك استخدام الشروط المتوقعةأو يمكنك ضبط تردد الاستطلاع باستخدام الانتظار بطلاقة. تجنب استخدام Thread.sleep ()، لأنه يوقف التنفيذ بشكل غير مشروط ويعتبر عموماً ممارسة سيئة.
في المثال أدناه، نقوم بإنشاء مرجع لـ WebDriverWait الفئة، قم بإنشاء نسخة منها باستخدام ويب درايفر قم بالرجوع إلى المرجع، وقم بضبط نافذة زمنية قصوى تبلغ 20 ثانية.
صيغة الانتظار الصريحة (Selenium 4):
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
package guru.test99;
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.Test;
public class AppTest2 {
protected WebDriver driver;
@Test
public void guru99tutorials() throws InterruptedException {
driver = new ChromeDriver();
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
String eTitle = "Demo Guru99 Page";
String aTitle = "";
// launch Chrome and redirect it to the Base URL
driver.get("https://demo.guru99.com/test/guru99home/");
// Maximize the browser window
driver.manage().window().maximize();
// get the actual value of the title
aTitle = driver.getTitle();
// compare the actual title with the expected title
if (aTitle.contentEquals(eTitle)) {
System.out.println("Test Passed");
} else {
System.out.println("Test Failed");
}
WebElement guru99seleniumlink;
guru99seleniumlink = wait.until(ExpectedConditions.visibilityOfElementLocated(
By.xpath("/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i")));
guru99seleniumlink.click();
}
}
شرح Code
ضع في اعتبارك الكود التالي:
WebElement guru99seleniumlink;
guru99seleniumlink = wait.until(ExpectedConditions.visibilityOfElementLocated(
By.xpath("/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i")));
guru99seleniumlink.click();
في مثال WebDriverWait هذا، ينتظر البرنامج النصي لمدة تصل إلى 20 ثانية، كما هو محدد بواسطة WebDriverWait الفصل، حتى الشروط المتوقعة يتم إرضاء الطرفين - أيهما يحدث أولاً.
ما سبق Java ينتظر البرنامج ما يصل إلى 20 ثانية حتى يتحقق الشرط. رؤية العنصر المحدد ليكون صحيحا.
يمكن استخدام الشروط المتوقعة التالية في Selenium انتظار صريح:
- تنبيهIsPresent()
- elementSelectionStateToBe()
- elementToBeClickable()
- ElementToBeSelected()
- FrameToBeAvailableAndSwitchToIt()
- invisibilityOfTheElementLocation()
- invisibilityOfElementWithText()
- وجودOfAllElementsLocatedBy()
- وجودOfElementLocation()
- textToBePresentInElement()
- textToBePresentInElementLocated()
- textToBePresentInElementValue()
- العنوان()
- يحتوي العنوان على()
- رؤية ()
- رؤيةOfAllElements()
- إمكانية الرؤيةOfAllElementsLocatedBy()
- إمكانية الرؤيةOfElementLocation()
انتظر بطلاقة Selenium
استخدم انتظر بطلاقة Selenium يُحدد هذا الإعداد الحد الأقصى لمدة انتظار WebDriver لتحقق شرط معين، بالإضافة إلى معدل التحقق من هذا الشرط قبل إطلاق استثناء ElementNotVisibleException. يتحقق Fluent Wait من وجود العنصر على فترات منتظمة حتى يتم العثور عليه أو انتهاء مهلة الانتظار.
التكرار دورة التكرار لتقييم الحالة على فترات منتظمة.
لنفترض سيناريو يتم فيه تحميل عنصر ما على فترات غير منتظمة. قد يستغرق تحميل العنصر 10 ثوانٍ، أو 20 ثانية، أو أكثر. إذا حددنا فترة انتظار صريحة مدتها 20 ثانية، فسينتظر البرنامج النصي المدة كاملة قبل أن يتوقف. في مثل هذه الحالات، يُعدّ Fluent Wait الخيار الأمثل لأنه يقوم بالتحقق من حالة العنصر بالتردد المحدد حتى يتم العثور عليه أو ينتهي المؤقت الأخير.
صيغة الانتظار السلسة (Selenium 4):
Wait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofSeconds(5))
.ignoring(NoSuchElementException.class);
تم إيقاف استخدام التوقيع القديم الذي كان يقبل قيمًا عددية صحيحة بالإضافة إلى وحدة الوقت في Selenium 3.11 وتمت إزالته في Selenium 4. واجهة برمجة التطبيقات القائمة على المدة الموضحة أعلاه هي النهج الموصى به حاليًا.
package guru.test99;
import java.time.Duration;
import java.util.NoSuchElementException;
import java.util.function.Function;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import org.testng.annotations.Test;
public class AppTest3 {
protected WebDriver driver;
@Test
public void guru99tutorials() throws InterruptedException {
String eTitle = "Demo Guru99 Page";
String aTitle = "";
driver = new ChromeDriver();
// launch Chrome and redirect it to the Base URL
driver.get("https://demo.guru99.com/test/guru99home/");
// Maximize the browser window
driver.manage().window().maximize();
// get the actual value of the title
aTitle = driver.getTitle();
// compare the actual title with the expected title
if (aTitle.contentEquals(eTitle)) {
System.out.println("Test Passed");
} else {
System.out.println("Test Failed");
}
Wait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofSeconds(5))
.ignoring(NoSuchElementException.class);
WebElement clickseleniumlink = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.xpath("/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i"));
}
});
// click on the selenium link
clickseleniumlink.click();
// close browser
driver.close();
}
}
شرح Code
ضع في اعتبارك الكود التالي:
Wait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofSeconds(5))
.ignoring(NoSuchElementException.class);
في المثال أعلاه، نُعلن عن انتظار سلس بمهلة زمنية قدرها 30 ثانية، وتردد استطلاع يبلغ 5 ثوانٍ، ونتجاهل NoSuchElementException.
ضع في اعتبارك الكود التالي:
public WebElement apply(WebDriver driver) {
return driver.findElement(By.xpath("/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i"));
}
تحدد هذه الوظيفة عنصر الويب على الصفحة (هنا، الـ Selenium (رابط على الصفحة الرئيسية). مع فاصل استطلاع مدته 5 ثوانٍ ومهلة زمنية مدتها 30 ثانية، يتحقق البرنامج النصي من وجود العنصر كل 5 ثوانٍ لمدة أقصاها 30 ثانية. إذا كان العنصر موجودًا ضمن هذه الفترة، يستمر البرنامج النصي في التنفيذ. وإلا، فإنه... ElementNotVisibleException هذا خطئ.
تحقق أيضا: Selenium دروس IDE للمبتدئين
الفرق بين الانتظار الضمني والانتظار الصريح
يوضح الجدول أدناه الاختلافات الرئيسية بين الانتظار الضمني والانتظار الصريح في Selenium.
| الانتظار الضمني | الانتظار الصريح |
|---|---|
| يتم تطبيق وقت الانتظار الضمني على جميع العناصر في البرنامج النصي. | يتم تطبيق وقت الانتظار الصريح فقط على العناصر المستهدفة تحديدًا. |
| في الانتظار الضمني، لا يتم تحديد الشروط المتوقعة للعنصر. | في حالة الانتظار الصريح، يجب تحديد الشروط المتوقعة للعنصر. |
| يُنصح باستخدامه عند تحميل العناصر ضمن نافذة الانتظار الضمنية المُحددة. | يوصى به عندما تستغرق العناصر وقتًا أطول للتحميل وعند التحقق من صحة حالات العناصر مثل visibilityOfElementLocated أو elementToBeClickable أو elementToBeSelected. |
| يتم تعيينه مرة واحدة ويتم تطبيقه طوال دورة حياة مثيل WebDriver. | قم بالتعيين لكل عنصر أو لكل فحص، مما يوفر تحكمًا أدق. |
كيفية اختيار استراتيجية الانتظار المناسبة
يؤثر اختيار أمر الانتظار الصحيح بشكل مباشر على استقرار البرنامج النصي ووقت تنفيذه. استخدم إطار العمل هذا لاختيار الخيار المناسب لكل سيناريو.
- حدد نمط الحمل: تحقق مما إذا كان العنصر يظهر في وقت محدد، بعد استجابة Ajax، أو على فترات غير متوقعة. تتناسب الأحمال الثابتة مع الانتظار الضمني، بينما تتطلب الأحمال غير المتوقعة الانتظار السلس.
- تجنب الخلط بين الانتظار الضمني والانتظار الصريح: قد يؤدي الجمع بين الأمرين إلى تأخيرات غير متوقعة لأن الانتظار الأطول قد يطغى. Selenium توصي الوثائق باستخدام استراتيجية واحدة فقط لكل جلسة WebDriver.
- الوضع الافتراضي: انتظار صريح للمحتوى الديناميكي: عندما تعتمد الصفحات على Ajax أو العرض المشروط أو الرسوم المتحركة، فإن Explicit Wait with ExpectedConditions يستهدف العنصر المهم بالضبط.
- استخدم خاصية الانتظار السلس للتوقيت المتغير: عندما يختلف توقيت تحميل العناصر بين عمليات التشغيل، قم بضبط Fluent Wait باستخدام فاصل زمني للاستقصاء. يقلل الاستقصاء من إجمالي وقت الانتظار مقارنةً بمهلة زمنية طويلة واحدة.
- استبدل Thread.sleep: تؤدي فترات الانتظار الثابتة إلى إبطاء مجموعات الاختبار وإخفاء مشاكل التوقيت الحقيقية. استبدلها بفترات انتظار مشروطة للحفاظ على سرعة التنفيذ وثباته.
- اضبط قيم مهلة الانتظار: ابدأ بمهلات قصيرة (5-10 ثوانٍ) وقم بزيادتها فقط عندما تُظهر الأعطال بطءًا حقيقيًا في التحميل. المهلات الافتراضية الطويلة تخفي تراجع الأداء.
- احتفظ بفترات الانتظار في الأدوات المساعدة: قم بتوحيد منطق الانتظار في فئة مساعدة بحيث يتم تطبيق تغييرات سياسة المهلة الزمنية على مجموعة الاختبار بأكملها.
باتباع هذا الإطار، يستطيع مهندسو الأتمتة بناء نصوص مرنة تتكيف مع توقيت التطبيق الحقيقي دون أن تصبح بطيئة أو هشة.
أخطاء شائعة يجب تجنبها Selenium ينتظر
حتى المختبرون ذوو الخبرة يقعون في مجموعة صغيرة من الأخطاء المتكررة عند العمل مع Selenium يؤدي تجنب هذه المشكلات إلى الحفاظ على سرعة البرامج النصية، وقدرتها على التنبؤ، وسهولة صيانتها عبر الفرق والبيئات المختلفة.
الخطأ الشائع الأول هو الإفراط في استخدام دالة Thread.sleep. يُجبر الإيقاف المؤقت المُبرمج مسبقًا البرنامج النصي على الانتظار طوال المدة المحددة بغض النظر عن توفر العنصر الفعلي، مما يزيد من وقت التشغيل الإجمالي. استبدل هذه الإيقافات المؤقتة بـ Explicit أو Fluent Wait حتى يستأنف البرنامج النصي عمله فور تحقق الشرط.
الخطأ الثاني هو الجمع بين الانتظار الضمني والصريح في نفس الاختبار. قد تتفاقم هذه الآلية، مما يؤدي إلى مهلات غير متوقعة يصعب تصحيحها. اختر استراتيجية واحدة لكل جلسة WebDriver وطبّقها باستمرار.
الخطأ الثالث هو تحديد فترات زمنية طويلة جدًا "احتياطًا". فالفترات الزمنية الافتراضية الطويلة تخفي مشاكل الأداء الحقيقية وتبطئ عملية التغذية الراجعة في مسارات التكامل المستمر. ابدأ بفترات زمنية قصيرة، وقم بتمديدها فقط عندما تثبت سجلات الأعطال وجود مشكلة توقيت حقيقية.
تحقق أيضا: Selenium برنامج تعليمي للمبتدئين: تعلم WebDriver في 7 أيام
