এলোমেলোভাবে "এলিমেন্টটি আর ডোমের সাথে সংযুক্ত থাকবে না" স্টলেএলিমেন্টরিফেকশন x


143

আমি আশা করছি এটি কেবল আমার, তবে সেলেনিয়াম ওয়েবড্রাইভার একটি সম্পূর্ণ দুঃস্বপ্নের মতো বলে মনে হচ্ছে। ক্রোম ওয়েবড্রাইভার বর্তমানে অকার্যকর এবং অন্যান্য চালকরা বেশ অবিশ্বস্ত, বা তাই মনে হচ্ছে। আমি অনেক সমস্যার সাথে লড়াই করছি, কিন্তু এখানে একটি।

এলোমেলোভাবে, আমার পরীক্ষাগুলি a দিয়ে ব্যর্থ হবে

"org.openqa.selenium.StaleElementReferenceException: Element is no longer attached 
to the DOM    
System info: os.name: 'Windows 7', os.arch: 'amd64',
 os.version: '6.1', java.version: '1.6.0_23'"

আমি ওয়েবড্রাইভার সংস্করণগুলি 2.0 বি 3 ব্যবহার করছি। আমি এফএফ এবং আইই ড্রাইভারগুলির সাথে এটি ঘটতে দেখেছি। আমি এটিকে প্রতিরোধ করতে Thread.sleepপারার একমাত্র উপায় হ'ল ব্যতিক্রম হওয়ার আগে একটি আসল কল যুক্ত করা । যদিও এটি একটি দুর্বল কাজ, তাই আমি আশা করছি যে কেউ আমার পক্ষ থেকে এমন একটি ত্রুটি চিহ্নিত করতে পারে যা এটি আরও ভাল করে তুলবে।


26
আশা করি 17 কে ভিউগুলি ইঙ্গিত দেয় যে এটি কেবল আপনিই নয়;) এটি সেখানে সবচেয়ে হতাশাজনক সেলেনিয়াম ব্যতিক্রম হতে পারে।
মায়ো

4
এখন 48k! আমারও একই সমস্যা ...
গ্যাল

3
আমি আবিষ্কার করছি যে সেলেনিয়াম খাঁটি এবং সম্পূর্ণ আবর্জনা ....
সি জনসন

4
60 কে, এখনও একটি ইস্যু :)
পিটার ডি বি

আমার ক্ষেত্রে এটি করার কারণে ছিলfrom selenium.common.exceptions import NoSuchElementException
সিপিটি। সেনকফাস

উত্তর:


119

হ্যাঁ, আপনি যদি স্টেলিএলিমেন্টরিফেরান এক্সেক্সসেপশন নিয়ে সমস্যা বোধ করেন তবে এটি আপনার পরীক্ষাগুলি খারাপভাবে লেখা হয়েছে বলে। এটি একটি জাতি শর্ত। নিম্নলিখিত পরিস্থিতিতে বিবেচনা করুন:

WebElement element = driver.findElement(By.id("foo"));
// DOM changes - page is refreshed, or element is removed and re-added
element.click();

এখন আপনি যে স্থানে উপাদানটি ক্লিক করছেন সেখানে এলিমেন্টের রেফারেন্সটি আর বৈধ নয়। এটি ঘটতে পারে এমন সমস্ত ক্ষেত্রেই ওয়েবড্রাইভারের পক্ষে ভাল ধারণা করা অসম্ভবের কাছাকাছি - সুতরাং এটি হাত বাড়িয়ে দেয় এবং আপনাকে নিয়ন্ত্রণ দেয়, যাকে পরীক্ষা / অ্যাপ লেখক হিসাবে ঠিক কী হতে পারে বা কী ঘটতে পারে তা জানতে হবে। আপনি যা করতে চান তা স্পষ্টভাবে অপেক্ষা করতে হবে যতক্ষণ না DOM এমন অবস্থায় থাকে যেখানে আপনি জানেন যে জিনিসগুলি পরিবর্তন হবে না। উদাহরণস্বরূপ, একটি নির্দিষ্ট উপাদান বিদ্যমান থাকার জন্য অপেক্ষা করার জন্য ওয়েবড্রাইভারওয়াইট ব্যবহার করে:

// times out after 5 seconds
WebDriverWait wait = new WebDriverWait(driver, 5);

// while the following loop runs, the DOM changes - 
// page is refreshed, or element is removed and re-added
wait.until(presenceOfElementLocated(By.id("container-element")));        

// now we're good - let's click the element
driver.findElement(By.id("foo")).click();

উপস্থিতিঅফিমেন্টলোকটেড () পদ্ধতিতে এরকম কিছু লাগবে:

private static Function<WebDriver,WebElement> presenceOfElementLocated(final By locator) {
    return new Function<WebDriver, WebElement>() {
        @Override
        public WebElement apply(WebDriver driver) {
            return driver.findElement(locator);
        }
    };
}

আপনি এখনকার ক্রোম ড্রাইভারটি বেশ অস্থির হওয়ার বিষয়ে ঠিক বলেছেন, এবং আপনি শুনে খুশি হবেন যে সেলেনিয়াম ট্রাঙ্কে একটি পুনর্লিখিত ক্রোম ড্রাইভার রয়েছে, যেখানে বেশিরভাগ বাস্তবায়ন ক্রোমিয়াম বিকাশকারীরা তাদের গাছের অংশ হিসাবে করেছিলেন।

পুনশ্চ. বিকল্পভাবে, উপরের উদাহরণের মতো স্পষ্টভাবে অপেক্ষা করার পরিবর্তে আপনি অন্তর্নিহিত অপেক্ষাগুলি সক্ষম করতে পারেন - এইভাবে ওয়েবড্রাইভার উপাদানটি উপস্থিত হওয়ার জন্য নির্দিষ্ট সময়সীমা অবধি অপেক্ষা করে সর্বদা লুপ আপ করবে:

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS)

যদিও আমার অভিজ্ঞতায় স্পষ্টতই অপেক্ষা করা সর্বদা আরও নির্ভরযোগ্য।


2
আমি কি ঠিক বলছি যে উপাদানগুলি ভেরিয়েবলগুলিতে পড়তে এবং সেগুলি পুনরায় ব্যবহার করা সম্ভব নয়? কারণ আমার কাছে একটি বিশাল শুকনো এবং গতিশীল ডাব্লু ওয়াটিআর ডিএসএল রয়েছে যা উত্তীর্ণ উপাদানগুলির উপর নির্ভর করে এবং আমি ওয়েবড্রাইভারে পোর্ট করার চেষ্টা করছি, তবে আমার একই সমস্যা হচ্ছে। মূলত আমাকে প্রতিটি পরীক্ষামূলক পদক্ষেপের জন্য মডিউলে সমস্ত উপাদান পুনরায় পড়তে কোড যুক্ত করতে হবে যা
ডমকে

ওহে. আমি উদাহরণস্বরূপ কোন ধরণের ফাংশনটি জিজ্ঞাসা করতে পারি? আমি এটি সন্ধান করতে পারে না .... ধন্যবাদ!
হ্যানিবাল

1
@ হানিবল:, পেয়ারাcom.google.common.base.Function<F, T> সরবরাহ করেছেন ।
স্টেফান202

@ জারিব, আপনার সমাধানের এক বছর পরেও আমি এই একই সমস্যার মুখোমুখি হয়েছি। সমস্যাটি হ'ল আমি আমার স্ক্রিপ্টগুলি রুবিতে লিখছি, এবং 'উপস্থিতিঅফিমেন্টলোকটেড' নামে বা এর মতো কোনও কিছুই নেই। কোন সুপারিশ?
আমে

56
@ জারিব আমি একমত নই যে এগুলি সবই খারাপ নকশাকৃত পরীক্ষার কারণে হয়েছিল। কারণ এজেএক্স কল করার পরেও উপাদানটি উপস্থিত হওয়ার পরেও সেখানে jQuery কোড চলতে পারে যা স্ট্যালিলমেন্টরিফারেন্সএক্সেপশন হতে পারে। এবং সুস্পষ্ট অপেক্ষা যোগ করা ছাড়া যা আপনি করতে পারেন কিছুই নেই যা খুব সুন্দর বলে মনে হয় না। আমি বরং মনে করি WebDriver মধ্যে একটি নকশা খুঁত নেই
মুখ না খুলিয়া চিবানো

10

আমি কিছু সাফল্যের সাথে এই জাতীয় পদ্ধতি ব্যবহার করতে সক্ষম হয়েছি:

WebElement getStaleElemById(String id) {
    try {
        return driver.findElement(By.id(id));
    } catch (StaleElementReferenceException e) {
        System.out.println("Attempting to recover from StaleElementReferenceException ...");
        return getStaleElemById(id);
    }
}

হ্যাঁ, এটি উপাদানটি পোলিং অবধি রাখে যতক্ষণ না এটি বাসি (তাজা?) হিসাবে বিবেচনা করে। আসলেই সমস্যার মূলে যায় না, তবে আমি খুঁজে পেয়েছি যে ওয়েবড্রাইভার এই ব্যতিক্রমটি ছুঁড়ে ফেলার বিষয়ে বাছাই করতে পারে - কখনও কখনও আমি এটি পাই, এবং কখনও কখনও পাই না। বা এটি হতে পারে যে ডম সত্যই পরিবর্তিত হচ্ছে।

সুতরাং আমি উপরের উত্তরের সাথে পুরোপুরি একমত নই যে এটি অগত্যা একটি খারাপ-লিখিত পরীক্ষা নির্দেশ করে। আমি তাজা পৃষ্ঠাগুলিতে পেয়েছি যা আমি কোনওভাবেই ইন্টারেক্ট করি নি। আমি মনে করি যে কোনওভাবে DOM কীভাবে উপস্থাপন করা হয় বা ওয়েবড্রাইভারকে বাসি বলে বিবেচনা করে তাতে কিছুটা স্বচ্ছলতা রয়েছে।


7
এই কোডটিতে আপনার একটি ত্রুটি রয়েছে, আপনার কোনও ধরণের টুপি ছাড়াই পুনরাবৃত্তভাবে পদ্ধতিটি কল করা উচিত নয় বা আপনি আপনার স্ট্যাকটি ফুটিয়ে তুলবেন।
হ্যারি

2
আমি মনে করি একটি কাউন্টার বা অন্য কিছু যুক্ত করা ভাল, সুতরাং আমরা যখন বারবার ত্রুটি পাচ্ছি, আমরা আসলে ত্রুটিটি ফেলে দিতে পারি। অন্যথায় যদি আসলে কোনও ত্রুটি ঘটে থাকে তবে আপনি একটি লুপে
এসে পৌঁছবেন

আমি সম্মত হই যে এটি খারাপ লিখিত পরীক্ষার ফলাফল নয়। আধুনিক ওয়েবসাইটগুলিতে সেলেনিয়ামের এটি করার প্রবণতা রয়েছে, এমনকি সেরা-লিখিত পরীক্ষার জন্যও - সম্ভবত কারণ ওয়েবসাইটগুলি প্রতিক্রিয়ার ওয়েব অ্যাপ্লিকেশন ফ্রেমওয়ার্কগুলিতে প্রচলিত সাধারণ দ্বি-মুখী বাইন্ডিংগুলির মাধ্যমে অবিচ্ছিন্নভাবে তাদের উপাদানগুলিকে সতেজ করে তুলছে, এমনকি তাতে কোনও পরিবর্তন নেই। সেই উপাদানগুলি তৈরি করা দরকার। এর মতো একটি পদ্ধতি প্রতিটি সেলেনিয়াম কাঠামোর একটি অংশ হওয়া উচিত যা একটি আধুনিক ওয়েব অ্যাপ্লিকেশন পরীক্ষা করে।
এমেরি

10

আমি কখনও কখনও যখন এজেএক্স আপডেটগুলি মাঝপথে থাকি তখন আমি এই ত্রুটিটি পাই। ডিওএম পরিবর্তনের জন্য অপেক্ষা করা সম্পর্কে ক্যাপিবারা বেশ স্মার্ট বলে মনে হচ্ছে (দেখুন কেন ক্যাপিবারা থেকে ওয়েট_ুনটিল অপসারণ করা হয়েছিল ), তবে আমার ক্ষেত্রে কেবল ২ সেকেন্ডের ডিফল্ট অপেক্ষার সময় যথেষ্ট ছিল না। উদাহরণস্বরূপ _spec_helper.rb_ এ পরিবর্তন হয়েছে

Capybara.default_max_wait_time = 5

2
এটি আমার সমস্যাটিকেও স্থির করে: আমি একটি স্টেলএলিমেন্টরিফারেন্স পেয়েছি এবং ক্যাপিবারা.ডেফল্ট_ম্যাক্স_উইট_ সময় সমস্যার সমাধান করেছি।
ব্রেন্ডন

1

আমি আজ একই সমস্যার মুখোমুখি হয়েছি এবং একটি মোড়কের ক্লাস তৈরি করেছি, যা উপাদানটির রেফারেন্সটি এখনও বৈধ কিনা প্রতিটি পদ্ধতির আগে পরীক্ষা করে। উপাদানটি পুনরুদ্ধার করার আমার সমাধানটি বেশ সহজ তাই আমি ভেবেছিলাম যে আমি এটি ভাগ করে নিই।

private void setElementLocator()
{
    this.locatorVariable = "selenium_" + DateTimeMethods.GetTime().ToString();
    ((IJavaScriptExecutor)this.driver).ExecuteScript(locatorVariable + " = arguments[0];", this.element);
}

private void RetrieveElement()
{
    this.element = (IWebElement)((IJavaScriptExecutor)this.driver).ExecuteScript("return " + locatorVariable);
}

আপনি দেখতে পাচ্ছেন আমি "সনাক্ত" বা তার পরিবর্তে বিশ্বব্যাপী জেএস ভেরিয়েবলটিতে উপাদানটি সংরক্ষণ করি এবং প্রয়োজনে উপাদানটি পুনরুদ্ধার করে। পৃষ্ঠাটি পুনরায় লোড হয়ে গেলে এই রেফারেন্সটি আর কাজ করবে না। তবে যতক্ষণ না ডুমের পরিবর্তন করা হয় ততক্ষণ রেফারেন্স থেকে যায়। এবং এটি বেশিরভাগ ক্ষেত্রেই কাজটি করা উচিত।

এছাড়াও এটি উপাদানটিকে পুনরায় অনুসন্ধান করা এড়িয়ে চলে।

জন


1

আমার একই সমস্যা ছিল এবং আমার একটি পুরানো সেলেনিয়াম সংস্করণ দ্বারা সৃষ্ট হয়েছিল। বিকাশের পরিবেশের কারণে আমি আরও নতুন সংস্করণে আপডেট করতে পারি না। HTMLUnitWebElement.switchFocusToThisIfNeeded () এর কারণে সমস্যাটি দেখা দেয়। আপনি যখন কোনও নতুন পৃষ্ঠায় নেভিগেট করেন তখন এটি হতে পারে যে আপনি যে উপাদানটি পুরানো পৃষ্ঠায় ক্লিক করেছেন তা হ'লoldActiveElement (নীচে দেখুন)। সেলেনিয়াম পুরানো উপাদানটির থেকে প্রসঙ্গটি পাওয়ার চেষ্টা করে এবং ব্যর্থ হয়। এ কারণেই তারা ভবিষ্যতে প্রকাশে একটি চেষ্টা করে।

সেলেনিয়াম-এইচটিএমএলটিউন-ড্রাইভার সংস্করণ <২.২৩.০ থেকে কোড:

private void switchFocusToThisIfNeeded() {
    HtmlUnitWebElement oldActiveElement =
        ((HtmlUnitWebElement)parent.switchTo().activeElement());

    boolean jsEnabled = parent.isJavascriptEnabled();
    boolean oldActiveEqualsCurrent = oldActiveElement.equals(this);
    boolean isBody = oldActiveElement.getTagName().toLowerCase().equals("body");
    if (jsEnabled &&
        !oldActiveEqualsCurrent &&
        !isBody) {
      oldActiveElement.element.blur();
      element.focus();
    }
}

সেলেনিয়াম-htmlunit- ড্রাইভার সংস্করণ থেকে কোড> = 2.23.0:

private void switchFocusToThisIfNeeded() {
    HtmlUnitWebElement oldActiveElement =
        ((HtmlUnitWebElement)parent.switchTo().activeElement());

    boolean jsEnabled = parent.isJavascriptEnabled();
    boolean oldActiveEqualsCurrent = oldActiveElement.equals(this);
    try {
        boolean isBody = oldActiveElement.getTagName().toLowerCase().equals("body");
        if (jsEnabled &&
            !oldActiveEqualsCurrent &&
            !isBody) {
        oldActiveElement.element.blur();
        }
    } catch (StaleElementReferenceException ex) {
      // old element has gone, do nothing
    }
    element.focus();
}

২.২৩.০ বা আরও নতুনতে আপডেট না করে আপনি কেবল পৃষ্ঠা ফোকাসে কোনও উপাদান দিতে পারেন। আমি কেবল element.click()উদাহরণ হিসাবে ব্যবহার করেছি ।


1
বাহ ... এটি সত্যিই অস্পষ্ট সন্ধান, সুন্দর কাজ ছিল .. আমি এখন ভাবছি যে অন্যান্য ড্রাইভারের (যেমন ক্রোমড্রাইভার) এরও একই সমস্যা রয়েছে
কেভেলার

0

সন্ধানের ইনপুট বাক্সে_কিগুলি প্রেরণ করার চেষ্টা করার সময় আমার সাথে ঘটেছিল - এতে আপনি কী টাইপ করেন তার উপর নির্ভর করে অটোপেটে রয়েছে E ইরোর উল্লেখ অনুসারে, ইনপুট উপাদানটির ভিতরে আপনার পাঠ্য টাইপ করার সময় আপনার উপাদানটি যদি কিছু অ্যাজাক্স আপডেট করে তবে এটি ঘটতে পারে । সমাধানটি হ'ল একবারে একটি অক্ষর পাঠানো এবং ইনপুট উপাদানটির জন্য আবার অনুসন্ধান করা । (উদাহরণস্বরূপ নীচে প্রদর্শিত রুবিতে)

def send_keys_eachchar(webdriver, elem_locator, text_to_send)
  text_to_send.each_char do |char|
    input_elem = webdriver.find_element(elem_locator)
    input_elem.send_keys(char)
  end
end

0

@ জারিবের উত্তরে যুক্ত করতে, আমি বেশ কয়েকটি এক্সটেনশন পদ্ধতি তৈরি করেছি যা রেসের শর্তটি দূর করতে সহায়তা করে।

এখানে আমার সেটআপ:

আমার কাছে "ড্রাইভার.সি" নামে একটি ক্লাস রয়েছে। এতে ড্রাইভার এবং অন্যান্য দরকারী স্ট্যাটিক ফাংশনগুলির জন্য এক্সটেনশন পদ্ধতিতে পূর্ণ একটি স্ট্যাটিক শ্রেণি রয়েছে।

যে উপাদানগুলির জন্য সাধারণত আমার পুনরুদ্ধার করা প্রয়োজন, আমি নিম্নলিখিতগুলির মতো একটি এক্সটেনশন পদ্ধতি তৈরি করি:

public static IWebElement SpecificElementToGet(this IWebDriver driver) {
    return driver.FindElement(By.SomeSelector("SelectorText"));
}

এটি আপনাকে কোড সহ কোনও পরীক্ষার শ্রেণী থেকে সেই উপাদানটি পুনরুদ্ধার করতে দেয়:

driver.SpecificElementToGet();

এখন, যদি এর ফলাফল হয় তবে StaleElementReferenceExceptionআমার ড্রাইভার ক্লাসে আমার কাছে নিম্নলিখিত স্থিতিশীল পদ্ধতি রয়েছে:

public static void WaitForDisplayed(Func<IWebElement> getWebElement, int timeOut)
{
    for (int second = 0; ; second++)
    {
        if (second >= timeOut) Assert.Fail("timeout");
        try
        {
            if (getWebElement().Displayed) break;
        }
        catch (Exception)
        { }
        Thread.Sleep(1000);
    }
}

এই ফাংশনটির প্রথম প্যারামিটারটি এমন কোনও ফাংশন যা কোনও আইওবিএলেমেন্ট অবজেক্ট দেয়। দ্বিতীয় প্যারামিটারটি সেকেন্ডে সময়সীমা হয় (টাইমআউটটির কোডটি ফায়ারফক্সের সেলেনিয়াম আইডিই থেকে অনুলিপি করা হয়েছিল)। কোডটি বাসি উপাদানটির ব্যতিক্রম নিম্নলিখিত উপায়ে এড়াতে ব্যবহার করা যেতে পারে:

MyTestDriver.WaitForDisplayed(driver.SpecificElementToGet,5);

উপরের কোডটি কোনও ব্যতিক্রম এবং মূল্যায়ন না করা driver.SpecificElementToGet().Displayedপর্যন্ত কল করবে willdriver.SpecificElementToGet().Displayedtrue এবং 5 সেকেন্ড অতিক্রান্ত হয় না। 5 সেকেন্ড পরে, পরীক্ষা ব্যর্থ হবে।

উল্টো দিকে, কোনও উপাদান উপস্থিত না হওয়ার জন্য অপেক্ষা করতে, আপনি নিম্নলিখিত ফাংশনটি একইভাবে ব্যবহার করতে পারেন:

public static void WaitForNotPresent(Func<IWebElement> getWebElement, int timeOut) {
    for (int second = 0;; second++) {
        if (second >= timeOut) Assert.Fail("timeout");
            try
            {
                if (!getWebElement().Displayed) break;
            }
            catch (ElementNotVisibleException) { break; }
            catch (NoSuchElementException) { break; }
            catch (StaleElementReferenceException) { break; }
            catch (Exception)
            { }
            Thread.Sleep(1000);
        }
}

0

আমি মনে করি স্ট্যালিলিটাররিফারেন্সএক্সেপশন হ্যান্ডেল করার জন্য আমি সুবিধাজনক পদ্ধতির সন্ধান পেয়েছি। ক্রিয়াগুলি আবার চেষ্টা করার জন্য আপনাকে প্রতিটি ওয়েবএলমেট পদ্ধতিতে মোড়ক লিখতে হয় যা হতাশাব্যঞ্জক এবং প্রচুর সময় নষ্ট করে।

এই কোড যুক্ত করা হচ্ছে

webDriverWait.until((webDriver1) -> (((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete")));

if ((Boolean) ((JavascriptExecutor) webDriver).executeScript("return window.jQuery != undefined")) {
    webDriverWait.until((webDriver1) -> (((JavascriptExecutor) webDriver).executeScript("return jQuery.active == 0")));
}

প্রতিটি ওয়েবএলমেন্ট ক্রিয়া আপনার পরীক্ষার স্থায়িত্ব বাড়িয়ে তুলতে পারার পরেও আপনি সময়ে সময়ে স্টেইলিমেন্টরিফেরান এক্সেক্সেশন পেতে পারেন।

সুতরাং এটিই আমি নিয়ে এসেছি (AspectJ ব্যবহার করে):

package path.to.your.aspects;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.RemoteWebElement;
import org.openqa.selenium.support.pagefactory.DefaultElementLocator;
import org.openqa.selenium.support.pagefactory.internal.LocatingElementHandler;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@Aspect
public class WebElementAspect {
    private static final Logger LOG = LogManager.getLogger(WebElementAspect.class);
    /**
     * Get your WebDriver instance from some kind of manager
     */
    private WebDriver webDriver = DriverManager.getWebDriver();
    private WebDriverWait webDriverWait = new WebDriverWait(webDriver, 10);

    /**
     * This will intercept execution of all methods from WebElement interface
     */
    @Pointcut("execution(* org.openqa.selenium.WebElement.*(..))")
    public void webElementMethods() {}

    /**
     * @Around annotation means that you can insert additional logic
     * before and after execution of the method
     */
    @Around("webElementMethods()")
    public Object webElementHandler(ProceedingJoinPoint joinPoint) throws Throwable {
        /**
         * Waiting until JavaScript and jQuery complete their stuff
         */
        waitUntilPageIsLoaded();

        /**
         * Getting WebElement instance, method, arguments
         */
        WebElement webElement = (WebElement) joinPoint.getThis();
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        Object[] args = joinPoint.getArgs();

        /**
         * Do some logging if you feel like it
         */
        String methodName = method.getName();

        if (methodName.contains("click")) {
            LOG.info("Clicking on " + getBy(webElement));
        } else if (methodName.contains("select")) {
            LOG.info("Selecting from " + getBy(webElement));
        } else if (methodName.contains("sendKeys")) {
            LOG.info("Entering " + args[0].toString() + " into " + getBy(webElement));
        }

        try {
            /**
             * Executing WebElement method
             */
            return joinPoint.proceed();
        } catch (StaleElementReferenceException ex) {
            LOG.debug("Intercepted StaleElementReferenceException");

            /**
             * Refreshing WebElement
             * You can use implementation from this blog
             * http://www.sahajamit.com/post/mystery-of-stale-element-reference-exception/
             * but remove staleness check in the beginning (if(!isElementStale(elem))), because we already caught exception
             * and it will result in an endless loop
             */
            webElement = StaleElementUtil.refreshElement(webElement);

            /**
             * Executing method once again on the refreshed WebElement and returning result
             */
            return method.invoke(webElement, args);
        }
    }

    private void waitUntilPageIsLoaded() {
        webDriverWait.until((webDriver1) -> (((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete")));

        if ((Boolean) ((JavascriptExecutor) webDriver).executeScript("return window.jQuery != undefined")) {
            webDriverWait.until((webDriver1) -> (((JavascriptExecutor) webDriver).executeScript("return jQuery.active == 0")));
        }
    }

    private static String getBy(WebElement webElement) {
        try {
            if (webElement instanceof RemoteWebElement) {
                try {
                    Field foundBy = webElement.getClass().getDeclaredField("foundBy");
                    foundBy.setAccessible(true);
                    return (String) foundBy.get(webElement);
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                }
            } else {
                LocatingElementHandler handler = (LocatingElementHandler) Proxy.getInvocationHandler(webElement);

                Field locatorField = handler.getClass().getDeclaredField("locator");
                locatorField.setAccessible(true);

                DefaultElementLocator locator = (DefaultElementLocator) locatorField.get(handler);

                Field byField = locator.getClass().getDeclaredField("by");
                byField.setAccessible(true);

                return byField.get(locator).toString();
            }
        } catch (IllegalAccessException | NoSuchFieldException e) {
            e.printStackTrace();
        }

        return null;
    }
}

এই দিকটি সক্ষম করতে ফাইল তৈরি করুন src\main\resources\META-INF\aop-ajc.xml এবং লিখুন

<aspectj>
    <aspects>
        <aspect name="path.to.your.aspects.WebElementAspect"/>
    </aspects>
</aspectj>

এটি আপনার যুক্ত করুন pom.xml

<properties>
    <aspectj.version>1.9.1</aspectj.version>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22.0</version>
            <configuration>
                <argLine>
                    -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                </argLine>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjweaver</artifactId>
                    <version>${aspectj.version}</version>
                </dependency>
            </dependencies>
        </plugin>
</build>

এবং যে সব. আশা করি এটা সাহায্য করবে.


0

আপনি সুস্পষ্ট অপেক্ষা ব্যবহার করে এটি সমাধান করতে পারেন যাতে আপনাকে কঠোর অপেক্ষা করতে না হয়।

যদি আপনি একটি বৈশিষ্ট্যযুক্ত সমস্ত উপাদান আনা এবং প্রতিটি লুপের জন্য এটির মাধ্যমে পুনরাবৃত্তি করে থাকেন তবে আপনি লুপের অভ্যন্তরে এইভাবে অপেক্ষা করতে পারেন,

List<WebElement> elements = driver.findElements("Object property");
for(WebElement element:elements)
{
    new WebDriverWait(driver,10).until(ExpectedConditions.presenceOfAllElementsLocatedBy("Object property"));
    element.click();//or any other action
}

বা একক উপাদানের জন্য আপনি নীচে কোড ব্যবহার করতে পারেন,

new WebDriverWait(driver,10).until(ExpectedConditions.presenceOfAllElementsLocatedBy("Your object property"));
driver.findElement("Your object property").click();//or anyother action 


-5
FirefoxDriver _driver = new FirefoxDriver();

// create webdriverwait
WebDriverWait wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(10));

// create flag/checker
bool result = false;

// wait for the element.
IWebElement elem = wait.Until(x => x.FindElement(By.Id("Element_ID")));

do
{
    try
    {
        // let the driver look for the element again.
        elem = _driver.FindElement(By.Id("Element_ID"));

        // do your actions.
        elem.SendKeys("text");

        // it will throw an exception if the element is not in the dom or not
        // found but if it didn't, our result will be changed to true.
        result = !result;
    }
    catch (Exception) { }
} while (result != true); // this will continue to look for the element until
                          // it ends throwing exception.

আমি এটি এখনই এটি বের করার পরে যুক্ত করেছি। বিন্যাসের জন্য দুঃখিত, এটি পোস্ট করার জন্য আমার প্রথমবার। শুধু সাহায্য করার চেষ্টা করছি। আপনি যদি এটি দরকারী মনে করেন তবে দয়া করে এটি অন্যকে ভাগ করুন :)
অ্যালভিন ভেরা

স্ট্যাকওভারফ্লোতে স্বাগতম! পোস্টের নির্ভুলতার উন্নতির জন্য একটি নমুনা কোডের জন্য একটি সংক্ষিপ্ত বিবরণ প্রদান করা সর্বদা ভাল :)
পিকরোফো সফটওয়্যার

উপরের কোডটি চালানো আপনি চিরতরে লুপে আটকে যেতে পারেন, উদাহরণস্বরূপ যদি সেই পৃষ্ঠাটিতে কোনও সার্ভার ত্রুটি থাকে।
মুখ না খুলিয়া চিবানো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.