нет такого исключения элемента при использовании Selenium с С#

У меня есть веб-страница в моем веб-проекте «CalculatorWeb», где я разместил одно текстовое поле с идентификатором «txtNum1».

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
    <form id="frmCalc">
        <div style="padding-top:20px;">
            My Sample Text Box <br/><br/>
            <input id="txtNum1" type="text" />
        </div>
    </form>
</body>
</html>

Ничего необычного, поэтому страница загружается, как показано ниже.

Предварительный просмотр веб-страницы

Теперь я создал файл функций «BrowserTest1.feature» для своего проекта «Calculator.Specs». Код следующим образом

Feature: BrowserTest1
In order to check url
As browser
I want to be see url of page

@mytag
Scenario: Go to URL
    Given I have entered 'http://localhost:58529/'
    When I go to that url
    Then there is a text box on the page with id 'txtNum1'

Затем я кодирую файл BrowserTest.cs для реализации модульных тестов.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using TechTalk.SpecFlow;

namespace Calculator.Specs
{
    [Binding]
    class BrowserTest
    {

        public string urlPath;


        [Given(@"I have entered 'http://localhost:58529/'")]
        protected void SetURL()
        {
            string URLPath = "http://localhost:58529/";
            urlPath = URLPath;
        }

        [When(@"I go to that url")]
        protected void NavigateToURL()
        {
             using (var driver = new ChromeDriver())
             {
                 driver.Navigate().GoToUrl(urlPath);
             }
        }


        [Then(@"there is a text box on the page with id 'txtNum1'")]
        protected void TxtBoxExists()
        {
            bool txtExists = false;
            using (var driver = new ChromeDriver())
            {
                IWebElement txtBox1 = driver.FindElement(By.Id("txtNum1"));

                if (txtBox1 != null)
                {
                    txtExists = true;
                }
            }
            Assert.AreEqual(true, txtExists);
        }
    }
}

Насколько мне известно, у меня есть все необходимые ссылки для Visual Studio IDE для интеграции SpecFlow/Selenium.

Раздел ссылок

Когда я запускаю модульный тест, веб-страница загружается нормально, однако я получаю неудачный тест, когда пытаюсь найти элемент с идентификатором «txtNum1», даже если текстовое поле с этим идентификатором существует на странице.

Сообщение об исключении

Сведения об исключении отображаются следующим образом.

Сведения об исключении

Может ли кто-нибудь указать мне правильное направление относительно того, что мне не хватает, чтобы позволить Selenium найти текстовое поле на странице с идентификатором «txtNum1»


person Asif    schedule 04.11.2014    source источник
comment
Просто первое предположение - не следует ли driver делиться между шагами?   -  person Konrad Kokosa    schedule 04.11.2014


Ответы (3)


вам нужно использовать один и тот же экземпляр драйвера между шагами, иначе драйвер, который переходит на страницу, отличается от драйвера, из которого вы пытаетесь получить элемент.

у вас есть несколько вариантов для этого. Самый простой — создать поле для экземпляра вашего драйвера и использовать его на всех этапах. Это будет работать до тех пор, пока все ваши шаги находятся в одном файле.

Другой вариант — сохранить объект драйвера в ScenarioContext.Current (или FeatureContext.Current). Это словари, поэтому вы можете сделать это:

ScenarioContext.Current["webDriver"] = driver;

Это будет работать нормально, но вам придется приводить каждый раз, когда вы получаете драйвер, поскольку словарь просто берет объекты, но вы сможете совместно использовать экземпляр драйвера между шагами независимо от того, в каком файле они находятся.

Третий (и лучший, ИМХО) вариант — создать класс WebDriverContext и принять его в конструкторе пошагового класса. Создайте свой драйвер один раз (в его конструкторе), а затем каждый шаг может использовать экземпляр WebDriverContext для доступа к общему драйверу.

Пример настройки можно увидеть в здесь

person Sam Holder    schedule 04.11.2014
comment
Да, это был тот. Хороший крик о настройке общего экземпляра для веб-драйвера - person Asif; 04.11.2014

Вашему водителю просто нужно двигаться немного медленнее

Добавьте некоторую задержку перед каждым driver.FindElement, например:

Thread.Sleep(2000);
IWebElement txtBox1 = driver.FindElement(By.Id("txtNum1"));

Или еще лучше:

WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0,0,10));
wait.Until(ExpectedConditions.ElementIsVisible(By.Id("txtNum1")));
IWebElement txtBox1 = driver.FindElement(By.Id("txtNum1"));
person codablank1    schedule 04.11.2014
comment
Спасибо за полезный совет. Может быть очень полезно, когда у нас есть большая страница для загрузки, и мы хотели бы, чтобы вся страница загружалась сначала, прежде чем искать элемент на ней. Хотя моя конкретная проблема была связана с дополнительным экземпляром драйвера Chrome. Один экземпляр загружал страницу, а другой оператор using использовался для проверки элемента на странице. Поскольку на втором экземпляре не загружена страница, поэтому он всегда возвращал не найденный элемент. - person Asif; 04.11.2014

Нашел ответ после небольшого изучения кода. Эта проблема была связана с несколькими экземплярами ChromeDriver в коде. Таким образом, первый экземпляр загружал страницу, но когда я пытался найти элемент на странице, я использовал новый экземпляр страницы вместо того, который уже использовался для загрузки страницы. Таким образом, этот второй экземпляр драйвера хрома без загруженной страницы всегда возвращал исключение, когда элемент не был найден, поскольку в этом экземпляре драйвера хрома не было загружено ни одной страницы.

person Asif    schedule 04.11.2014