我有两个功能(我刚刚开始使用SpecFlow)在每个功能步骤中,我创建了一个全局WebDriver,以便我可以将它用于所有步骤。如果我只运行这些步骤,一切都在两个功能中正确运行。但是,它们会使浏览器窗口保持打开状态,因为我从不关闭WebDriver。所以我的想法是在每个Step文件中放置一个AfterFeature夹具来关闭驱动程序。
[AfterFeature]
public static void ShutDown()
{
Driver.Close();
}
当我运行每个功能时,一切都很好,驱动程序在运行结束时关闭。但是,如果我运行这样的多个功能,驱动程序将在第一个功能之后关闭,并且在下一个功能启动时将不会打开新功能。我发现这很奇怪,因为每个功能步骤文件都有自己的实例化驱动程序。
我了解到,如果我使用[AfterTestRun],测试将正确运行,两个浏览器将保持打开状态,直到所有功能都完成。在这一点上,他们都将关闭。当我只有两个功能时,这是好的,但当我得到一堆,我宁愿没有一堆随机的浏览器窗口,直到所有的测试都完成。
我认为这可能与我无法在不破坏测试的情况下使用[AfterScenario]有关。我试图在每个场景/测试后使用[AfterScenario]注销,但是当我这样做时,我看到在第一次测试结束时弹出一个随机的空白驱动程序/浏览器窗口(无论我先运行哪个测试)。
我有这种感觉,我只是缺少这种整体BDD方法的某种范式,并且事实上实际上是按设计工作的。但我不知道应该做些什么改变。这是我的登录测试的一个例子..我在这里缺少一些基本的东西吗?
Login.feature
Feature: Login
In order to be able to use Laserfiche
As a legitimate user
I want to be able to log into the repository
@SmokeTest
Scenario: Login with correct credentials
Given I am on the Login page
And I have a good username/password combination
And I select a repository
When I fill out the form and submit
Then I am taken to the repo page
---------------
LoginSteps.cs
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Selenium_C_Sharp_POC.Page_Object_Files.Pages;
using Selenium_C_Sharp_POC.Page_Object_Files.Test_Tools;
using TechTalk.SpecFlow;
namespace Selenium_C_Sharp_POC.StepDefinitions
{
[Binding]
public class LoginSteps
{
private static readonly IWebDriver Driver = new ChromeDriver();
private static LoginPage _loginPage;
private static string _username;
private static string _password;
private static string _repo;
[AfterTestRun]
public static void ShutDown()
{
Driver?.Close();
}
[Given(@"I am on the Login page")]
public void GivenIAmOnTheLoginPage()
{
_loginPage = new LoginPage(Driver);
}
[Given(@"I have a good username/password combination")]
public void GivenIHaveAGoodUsernamePasswordCombination()
{
_username = Nomenclature.WebClientPersonalUsername;
_password = Nomenclature.WebClientPersonalPassword;
}
[Given(@"I select a repository")]
public void GivenISelectARepository()
{
_repo = Nomenclature.RepoUnderTest;
}
[When(@"I fill out the form and submit")]
public void WhenIFillOutTheFormAndSubmit()
{
_loginPage.Login(
username: _username,
password: _password,
repo: _repo);
}
[Then(@"I am taken to the repo page")]
public void ThenIAmTakenToTheRepoPage()
{
Assert.AreEqual(
expected: _repo,
actual: Driver.Title);
HelperMethods.Logout(Driver);
}
}
}
using System;
using OpenQA.Selenium;
using System.Threading;
using OpenQA.Selenium.Support.UI;
using SeleniumExtras.WaitHelpers;
using Selenium_C_Sharp_POC.Page_Object_Files.Test_Tools;
namespace Selenium_C_Sharp_POC.Page_Object_Files.Pages
{
class LoginPage
{
private readonly IWebElement _repoDropDown;
private readonly IWebElement _usernameTextBox;
private readonly IWebElement _passwordTextBox;
private readonly IWebElement _submitButton;
private readonly IWebDriver _driver;
private readonly IWebElement _warningBox;
public LoginPage(IWebDriver driver)
{
_driver = driver;
HelperMethods.OpenWebPage(
domain: Nomenclature.Domain,
driver: _driver,
subPage: Nomenclature.LoginPageFilename
);
_repoDropDown = _driver.FindElement(By.Id("SelectedRepo"));
_passwordTextBox = _driver.FindElement(By.Name("password"));
_usernameTextBox = _driver.FindElement(By.Name("username"));
_submitButton = _driver.FindElement(By.Id("LoginButton"));
_warningBox = _driver.FindElement(By.ClassName("alert-danger"));
}
public void Login(string username, string password, string repo)
{
SelectRepo(repo);
_usernameTextBox.SendKeys(username);
_passwordTextBox.SendKeys(password);
_submitButton.Click();
WaitForLoginToComplete();
}
public void SelectRepo(string repo)
{
_repoDropDown.Click();
var options = _repoDropDown.FindElements(By.XPath(".//option"));
foreach (var option in options)
{
if(option.Text.Equals(repo))
option.Click();
}
}
public bool WarningDisplayed_UsernamePassword()
{
Thread.Sleep(500);
return _warningBox.Displayed &&
_warningBox.Text.Equals(Nomenclature.BadUsernameOrPasswordText, StringComparison.OrdinalIgnoreCase);
}
internal bool OpenedRepoPage(string expectedRepo)
{
return _driver.Title.Equals(expectedRepo);
}
internal void WaitForLoginToComplete()
{
try
{
var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(5));
wait.Until(ExpectedConditions.ElementIsVisible(By.ClassName("alert-danger")));
}
catch (Exception)
{
var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(45));
wait.Until(ExpectedConditions.ElementExists(By.XPath("//*[@ng-model='searchQuery']")));
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName("entryListLoadingSpinner")));
}
}
}
}
我相信我知道为什么会这样。我只是不知道解决它的正确方法。作为一项实验,我将我的搜索测试的WebDriver更改为Firefox,并将WebDriver作为Chrome进行登录测试。无论我跑了什么样的测试,我总是看到2个浏览器打开;一个Chrome和一个Firefox。
当我将SearchTestSteps.cs文件中的所有步骤移动到LoginTestSteps.cs文件中时,问题就消失了。
所以,是的,这解决了眼前的问题,但将所有步骤放在一个文件中并不是最佳的。这很快就会变得笨拙。
由于每组步骤都需要有自己的WebDriver,所以我很茫然。
这可能与文件夹结构和存储内容有关吗?这是我的样子。
Root
|-Page Object Files
|- Page Components
|- Pages
|- Test Tools
|- Step Definitions
|- <*Steps.cs>
|- TESTS
|- BDD Tests
|-<*.feature>
|- *standard selenium test files*
在调查了一些之后,我意识到问题不是我想象的那样,因此标题和内容都是不准确的。我正在关闭这个问题并创建一个更准确的标题和信息的新问题。