Saya berharap ini hanya saya, tetapi Selenium Webdriver sepertinya seperti mimpi buruk. Webdriver Chrome saat ini tidak dapat digunakan, dan driver lain cukup tidak dapat diandalkan, atau sepertinya begitu. Saya menghadapi banyak masalah, tetapi ini adalah salah satunya.
Secara acak, pengujian saya akan gagal dengan 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'"
Saya menggunakan versi webdriver 2.0b3. Saya telah melihat ini terjadi dengan driver FF dan IE. Satu-satunya cara saya dapat mencegah ini adalah dengan menambahkan panggilan aktual Thread.sleep
sebelum pengecualian terjadi. Itu adalah solusi yang buruk, jadi saya berharap seseorang dapat menunjukkan kesalahan pada bagian saya yang akan membuat ini semua lebih baik.
java
selenium-webdriver
webdriver
automated-tests
Ray Nicholus
sumber
sumber
from selenium.common.exceptions import NoSuchElementException
Jawaban:
Ya, jika Anda mengalami masalah dengan StaleElementReferenceExceptions itu karena tes Anda ditulis dengan buruk. Ini kondisi balapan. Pertimbangkan skenario berikut:
Sekarang pada titik di mana Anda mengklik elemen, referensi elemen tidak lagi valid. Hampir tidak mungkin bagi WebDriver untuk membuat perkiraan yang baik tentang semua kasus di mana ini mungkin terjadi - jadi itu mengangkat tangannya dan memberikan kontrol kepada Anda, yang sebagai penulis tes / aplikasi harus tahu persis apa yang mungkin atau mungkin tidak terjadi. Yang ingin Anda lakukan adalah menunggu secara eksplisit hingga DOM berada dalam kondisi di mana Anda tahu segala sesuatu tidak akan berubah. Misalnya, menggunakan WebDriverWait untuk menunggu elemen tertentu ada:
Metode presenceOfElementLocated () akan terlihat seperti ini:
Anda cukup benar tentang driver Chrome saat ini yang cukup tidak stabil, dan Anda akan senang mendengar bahwa bagasi Selenium memiliki driver Chrome yang ditulis ulang, di mana sebagian besar implementasinya dilakukan oleh pengembang Chromium sebagai bagian dari pohon mereka.
PS. Sebagai alternatif, alih-alih menunggu secara eksplisit seperti pada contoh di atas, Anda dapat mengaktifkan menunggu secara implisit - dengan cara ini WebDriver akan selalu berulang hingga batas waktu yang ditentukan menunggu elemen menjadi ada:
Dalam pengalaman saya, menunggu secara eksplisit selalu lebih dapat diandalkan.
sumber
com.google.common.base.Function<F, T>
disediakan oleh Guava .Saya telah dapat menggunakan metode seperti ini dengan beberapa keberhasilan:
Ya, itu hanya terus mengumpulkan elemen sampai tidak lagi dianggap basi (segar?). Tidak benar-benar sampai ke akar masalahnya, tetapi saya telah menemukan bahwa WebDriver bisa agak pilih-pilih untuk melempar pengecualian ini - kadang-kadang saya mendapatkannya, dan kadang-kadang tidak. Atau bisa jadi DOM benar-benar berubah.
Jadi saya tidak setuju dengan jawaban di atas bahwa ini tentu menunjukkan tes yang ditulis dengan buruk. Saya mendapatkannya di halaman baru yang saya belum berinteraksi dengan cara apa pun. Saya pikir ada beberapa kelemahan dalam bagaimana DOM diwakili, atau dalam apa yang dianggap WebDriver basi.
sumber
Saya mendapatkan kesalahan ini kadang-kadang ketika pembaruan AJAX di tengah jalan. Capybara tampaknya cukup pintar menunggu perubahan DOM (lihat Mengapa wait_until dihapus dari Capybara ), tetapi waktu tunggu default 2 detik tidak cukup dalam kasus saya. Berubah _spec_helper.rb_ dengan misalnya
sumber
Saya menghadapi masalah yang sama hari ini dan membuat kelas pembungkus, yang memeriksa sebelum setiap metode jika referensi elemen masih valid. Solusi saya untuk retrive elemen cukup sederhana jadi saya pikir saya baru saja membagikannya.
Anda melihat saya "mencari" atau lebih tepatnya menyimpan elemen dalam variabel global js dan mengambil elemen jika diperlukan. Jika halaman dimuat ulang referensi ini tidak akan berfungsi lagi. Tetapi selama hanya perubahan yang dilakukan untuk menghancurkan referensi tetap. Dan itu harusnya berhasil dalam banyak kasus.
Juga menghindari pencarian ulang elemen.
John
sumber
Saya memiliki masalah yang sama dan masalah saya disebabkan oleh versi selenium lama. Saya tidak dapat memperbarui ke versi yang lebih baru karena lingkungan pengembangan. Masalahnya disebabkan oleh HTMLUnitWebElement.switchFocusToThisIfNeeded (). Ketika Anda menavigasi ke halaman baru, mungkin terjadi bahwa elemen yang Anda klik pada halaman lama adalah
oldActiveElement
(lihat di bawah). Selenium mencoba untuk mendapatkan konteks dari elemen yang lama dan gagal. Itu sebabnya mereka membuat try catch di rilis mendatang.Kode dari versi selenium-htmlunit-driver <2.23.0:
Kode dari versi selenium-htmlunit-driver> = 2.23.0:
Tanpa memperbarui ke 2.23.0 atau yang lebih baru, Anda bisa memberikan elemen apa saja pada fokus halaman. Saya hanya menggunakan
element.click()
misalnya.sumber
Kebetulan saya ketika mencoba mengirim_keys ke kotak input pencarian - yang memiliki pembaruan otomatis tergantung pada apa yang Anda ketik. Seperti yang disebutkan oleh Eero, ini dapat terjadi jika elemen Anda melakukan beberapa pembaruan Ajax saat Anda mengetik teks di dalam elemen input . Solusinya adalah mengirim satu karakter sekaligus dan mencari lagi elemen input . (Mis. Dalam rubi yang ditunjukkan di bawah)
sumber
Untuk menambah jawaban @ jarib, saya telah membuat beberapa metode ekstensi yang membantu menghilangkan kondisi balapan.
Ini pengaturan saya:
Saya memiliki kelas yang disebut "Driver.cs". Ini berisi kelas statis penuh metode ekstensi untuk driver dan fungsi statis lain yang berguna.
Untuk elemen yang biasanya perlu saya ambil, saya membuat metode ekstensi seperti berikut:
Ini memungkinkan Anda untuk mengambil elemen itu dari kelas tes apa pun dengan kode:
Sekarang, jika ini menghasilkan a
StaleElementReferenceException
, saya memiliki metode statis berikut di kelas driver saya:Parameter pertama fungsi ini adalah fungsi apa pun yang mengembalikan objek IWebElement. Parameter kedua adalah batas waktu dalam detik (kode untuk batas waktu itu disalin dari Selenium IDE untuk FireFox). Kode dapat digunakan untuk menghindari pengecualian elemen basi dengan cara berikut:
Kode di atas akan memanggil
driver.SpecificElementToGet().Displayed
hinggadriver.SpecificElementToGet()
tidak ada pengecualian dan.Displayed
mengevaluasi hinggatrue
5 detik belum berlalu. Setelah 5 detik, tes akan gagal.Di sisi lain, untuk menunggu elemen tidak ada, Anda dapat menggunakan fungsi berikut dengan cara yang sama:
sumber
Saya rasa saya menemukan pendekatan yang mudah untuk menangani StaleElementReferenceException. Biasanya Anda harus menulis pembungkus untuk setiap metode WebElement untuk mencoba lagi tindakan, yang membuat frustrasi dan menghabiskan banyak waktu.
Menambahkan kode ini
sebelum setiap tindakan WebElement dapat meningkatkan stabilitas tes Anda, tetapi Anda masih bisa mendapatkan StaleElementReferenceException dari waktu ke waktu.
Jadi ini yang saya buat (menggunakan AspectJ):
Untuk mengaktifkan aspek ini buat file
src\main\resources\META-INF\aop-ajc.xml
dan tulisTambahkan ini ke
pom.xml
Dan itu saja. Semoga ini bisa membantu.
sumber
Anda dapat menyelesaikan ini dengan menggunakan tunggu eksplisit sehingga Anda tidak perlu menggunakan menunggu keras.
Jika Anda mengambil semua elemen dengan satu properti dan mengulanginya menggunakan setiap loop yang bisa Anda gunakan tunggu di dalam loop seperti ini,
atau untuk elemen tunggal Anda dapat menggunakan kode di bawah ini,
sumber
Di Java 8 Anda dapat menggunakan metode yang sangat sederhana untuk itu:
sumber
sumber