Andrew Knight delivered a session on "The Screenplay Pattern: Better Interactions for Better Automation" at #SeleniumSummit21
Andrew is the “Automation Panda” – an engineer, consultant, and international speaker who builds solutions for software testing problems. He has designed and built robust test automation projects for operating systems, service APIs, and Web apps with thousands of tests running continuously. He is the lead developer for Boa Constrictor, the .NET Screenplay Pattern.
To know more about #SeleniumSummit21 please check :
https://seleniumsummit21.agiletestingalliance.org/
15. IWebDriver driver = new ChromeDriver();
// Open the search engine
driver.Navigate().GoToUrl("https://duckduckgo.com/");
16. IWebDriver driver = new ChromeDriver();
// Open the search engine
driver.Navigate().GoToUrl("https://duckduckgo.com/");
// Search for a phrase
driver.FindElement(By.Id("search_form_input_homepage")).SendKeys("panda");
driver.FindElement(By.Id("search_button_homepage")).Click();
17. IWebDriver driver = new ChromeDriver();
// Open the search engine
driver.Navigate().GoToUrl("https://duckduckgo.com/");
// Search for a phrase
driver.FindElement(By.Id("search_form_input_homepage")).SendKeys("panda");
driver.FindElement(By.Id("search_button_homepage")).Click();
// Verify results appear
driver.Title.ToLower().Should().Contain("panda");
driver.FindElements(By.CssSelector("a.result__a")).Should().BeGreaterThan(0);
18. IWebDriver driver = new ChromeDriver();
// Open the search engine
driver.Navigate().GoToUrl("https://duckduckgo.com/");
// Search for a phrase
driver.FindElement(By.Id("search_form_input_homepage")).SendKeys("panda");
driver.FindElement(By.Id("search_button_homepage")).Click();
// Verify results appear
driver.Title.ToLower().Should().Contain("panda");
driver.FindElements(By.CssSelector("a.result__a")).Should().BeGreaterThan(0);
driver.Quit();
19. IWebDriver driver = new ChromeDriver();
// Open the search engine
driver.Navigate().GoToUrl("https://duckduckgo.com/");
// Search for a phrase
driver.FindElement(By.Id("search_form_input_homepage")).SendKeys("panda");
driver.FindElement(By.Id("search_button_homepage")).Click();
// Verify results appear
driver.Title.ToLower().Should().Contain("panda");
driver.FindElements(By.CssSelector("a.result__a")).Should().BeGreaterThan(0);
driver.Quit();
20. IWebDriver driver = new ChromeDriver();
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30);
// Open the search engine
driver.Navigate().GoToUrl("https://duckduckgo.com/");
// Search for a phrase
driver.FindElement(By.Id("search_form_input_homepage")).SendKeys("panda");
driver.FindElement(By.Id("search_button_homepage")).Click();
// Verify results appear
driver.Title.ToLower().Should().Contain("panda");
driver.FindElements(By.CssSelector("a.result__a")).Should().BeGreaterThan(0);
driver.Quit();
21. IWebDriver driver = new ChromeDriver();
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
// Open the search engine
driver.Navigate().GoToUrl("https://duckduckgo.com/");
// Search for a phrase
wait.Until(d => d.FindElements(By.Id("search_form_input_homepage")).Count > 0);
driver.FindElement(By.Id("search_form_input_homepage")).SendKeys("panda");
driver.FindElement(By.Id("search_button_homepage")).Click();
// Verify results appear
wait.Until(d => d.Title.ToLower().Contains("panda"));
wait.Until(d => d.FindElements(By.CssSelector("a.result__a"))).Count > 0);
driver.Quit();
22. IWebDriver driver = new ChromeDriver();
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
// Open the search engine
driver.Navigate().GoToUrl("https://duckduckgo.com/");
// Search for a phrase
wait.Until(d => d.FindElements(By.Id("search_form_input_homepage")).Count > 0);
driver.FindElement(By.Id("search_form_input_homepage")).SendKeys("panda");
driver.FindElement(By.Id("search_button_homepage")).Click();
// Verify results appear
wait.Until(d => d.Title.ToLower().Contains("panda"));
wait.Until(d => d.FindElements(By.CssSelector("a.result__a"))).Count > 0);
driver.Quit();
25. public class SearchPage
{
public const string Url = "https://duckduckgo.com/";
public static By SearchInput => By.Id("search_form_input_homepage");
public static By SearchButton => By.Id("search_button_homepage");
}
26. public class SearchPage
{
public const string Url = "https://duckduckgo.com/";
public static By SearchInput => By.Id("search_form_input_homepage");
public static By SearchButton => By.Id("search_button_homepage");
public IWebDriver Driver { get; private set; }
public SearchPage(IWebDriver driver) => Driver = driver;
}
27. public class SearchPage
{
public const string Url = "https://duckduckgo.com/";
public static By SearchInput => By.Id("search_form_input_homepage");
public static By SearchButton => By.Id("search_button_homepage");
public IWebDriver Driver { get; private set; }
public SearchPage(IWebDriver driver) => Driver = driver;
public void Load() => driver.Navigate().GoToUrl(Url);
}
28. public class SearchPage
{
public const string Url = "https://duckduckgo.com/";
public static By SearchInput => By.Id("search_form_input_homepage");
public static By SearchButton => By.Id("search_button_homepage");
public IWebDriver Driver { get; private set; }
public SearchPage(IWebDriver driver) => Driver = driver;
public void Load() => driver.Navigate().GoToUrl(Url);
public void Search(string phrase)
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
wait.Until(d => d.FindElements(SearchInput).Count > 0);
driver.FindElement(SearchInput).SendKeys(phrase);
driver.FindElement(SearchButton).Click();
}
}
29. IWebDriver driver = new ChromeDriver();
SearchPage searchPage = new SearchPage(driver);
searchPage.Load();
searchPage.Search(“panda”);
30. IWebDriver driver = new ChromeDriver();
SearchPage searchPage = new SearchPage(driver);
searchPage.Load();
searchPage.Search(“panda”);
ResultPage resultPage = new ResultPage(driver);
resultPage.WaitForTitle(“panda”);
resultPage.WaitForResultLinks();
driver.Quit();
36. public class BasePage
{
public IWebDriver Driver { get; private set; }
public WebDriverWait Wait { get; private set; }
public SearchPage(IWebDriver driver)
{
Driver = driver;
Wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(30));
}
}
37. public class BasePage
{
public IWebDriver Driver { get; private set; }
public WebDriverWait Wait { get; private set; }
public SearchPage(IWebDriver driver)
{
Driver = driver;
Wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(30));
}
protected void Click(By locator)
{
Wait.Until(d => d.FindElements(locator).Count > 0);
driver.FindElement(locator).Click();
}
}
38. public class AnyPage : BasePage
{
// ...
public AnyPage(IWebDriver driver) : base(driver) {}
public void ClickButton() => Click(Button);
public void ClickOtherButton() => Click(OtherButton);
}
39. public class AnyPage : BasePage
{
// ...
public void ClickButton() => Click(Button);
public void ClickOtherButton() => Click(OtherButton);
public void ButtonText() => Text(Button);
public void OtherButtonText() => Text(OtherButton);
public void IsButtonDisplayed() => IsDisplayed(Button);
public void IsButtonDisplayed() => IsDisplayed(OtherButton);
}
52. // NuGet Packages:
// Boa.Constrictor
// FluentAssertions
// Selenium.Support
// Selenium.WebDriver
using Boa.Constrictor.Logging;
using Boa.Constrictor.Screenplay;
using Boa.Constrictor.WebDriver;
using FluentAssertions;
using OpenQA.Selenium.Chrome;
using static Boa.Constrictor.WebDriver.WebLocator;
53. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
54. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
55. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
public class BrowseTheWeb : IAbility
{
public IWebDriver WebDriver { get; }
private BrowseTheWeb(IWebDriver driver) =>
WebDriver = driver;
public static BrowseTheWeb With(IWebDriver driver) =>
new BrowseTheWeb(driver);
}
56. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
public static class SearchPage
{
public const string Url =
"https://www.duckduckgo.com/";
public static IWebLocator SearchInput => L(
"DuckDuckGo Search Input",
By.Id("search_form_input_homepage"));
}
57. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
58. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
public void AttemptsTo(ITask task)
{
task.PerformAs(this);
}
59. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
public class Navigate : ITask
{
private string Url { get; set; }
private Navigate(string url) => Url = url;
public static Navigate ToUrl(string url) => new Navigate(url);
public void PerformAs(IActor actor)
{
var driver = actor.Using<BrowseTheWeb>().WebDriver;
driver.Navigate().GoToUrl(Url);
}
}
60. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
public class Navigate : ITask
{
private string Url { get; set; }
private Navigate(string url) => Url = url;
public static Navigate ToUrl(string url) => new Navigate(url);
public void PerformAs(IActor actor)
{
var driver = actor.Using<BrowseTheWeb>().WebDriver;
driver.Navigate().GoToUrl(Url);
}
}
61. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
public static class SearchPage
{
public const string Url =
"https://www.duckduckgo.com/";
public static IWebLocator SearchInput => L(
"DuckDuckGo Search Input",
By.Id("search_form_input_homepage"));
}
62. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
63. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
public TAnswer AskingFor<TAnswer>(IQuestion<TAnswer> question)
{
return question.RequestAs(this);
}
64. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
public class ValueAttribute : IQuestion<string>
{
public IWebLocator Locator { get; }
private ValueAttribute(IWebLocator locator) => Locator = locator;
public static ValueAttribute Of(IWebLocator locator) => new ValueAttribute(locator);
public string RequestAs(IActor actor)
{
var driver = actor.Using<BrowseTheWeb>().WebDriver;
actor.AttemptsTo(Wait.Until(Existence.Of(Locator), IsEqualTo.True()));
return driver.FindElement(Locator.Query).GetAttribute("value");
}
}
65. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
public class ValueAttribute : IQuestion<string>
{
public IWebLocator Locator { get; }
private ValueAttribute(IWebLocator locator) => Locator = locator;
public static ValueAttribute Of(IWebLocator locator) => new ValueAttribute(locator);
public string RequestAs(IActor actor)
{
var driver = actor.Using<BrowseTheWeb>().WebDriver;
actor.AttemptsTo(Wait.Until(Existence.Of(Locator), IsEqualTo.True()));
return driver.FindElement(Locator.Query).GetAttribute("value");
}
}
66. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
public static class SearchPage
{
public const string Url =
"https://www.duckduckgo.com/";
public static IWebLocator SearchInput => L(
"DuckDuckGo Search Input",
By.Id("search_form_input_homepage"));
}
67. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
68. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
actor.AttemptsTo(SearchDuckDuckGo.For("panda"));
69. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
actor.AttemptsTo(SearchDuckDuckGo.For("panda"));
public class SearchDuckDuckGo : ITask
{
public string Phrase { get; }
private SearchDuckDuckGo(string phrase) =>
Phrase = phrase;
public static SearchDuckDuckGo For(string phrase) =>
new SearchDuckDuckGo(phrase);
public void PerformAs(IActor actor)
{
actor.AttemptsTo(SendKeys.To(SearchPage.SearchInput, Phrase));
actor.AttemptsTo(Click.On(SearchPage.SearchButton));
}
}
70. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
actor.AttemptsTo(SearchDuckDuckGo.For("panda"));
public class SearchDuckDuckGo : ITask
{
public string Phrase { get; }
private SearchDuckDuckGo(string phrase) =>
Phrase = phrase;
public static SearchDuckDuckGo For(string phrase) =>
new SearchDuckDuckGo(phrase);
public void PerformAs(IActor actor)
{
actor.AttemptsTo(SendKeys.To(SearchPage.SearchInput, Phrase));
actor.AttemptsTo(Click.On(SearchPage.SearchButton));
}
}
71. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
actor.AttemptsTo(SearchDuckDuckGo.For("panda"));
72. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
actor.AttemptsTo(SearchDuckDuckGo.For("panda"));
actor.AttemptsTo(Wait.Until(Appearance.Of(ResultPage.ResultLinks), IsEqualTo.True()));
73. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
actor.AttemptsTo(SearchDuckDuckGo.For("panda"));
actor.AttemptsTo(Wait.Until(Appearance.Of(ResultPage.ResultLinks), IsEqualTo.True()));
74. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
actor.AttemptsTo(SearchDuckDuckGo.For("panda"));
actor.AttemptsTo(Wait.Until(Appearance.Of(ResultPage.ResultLinks), IsEqualTo.True()));
public static IWebLocator ResultLinks => L(
"DuckDuckGo Result Page Links",
By.ClassName("result__a"));
75. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
actor.AttemptsTo(SearchDuckDuckGo.For("panda"));
actor.AttemptsTo(Wait.Until(Appearance.Of(ResultPage.ResultLinks), IsEqualTo.True()));
76. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
actor.AttemptsTo(SearchDuckDuckGo.For("panda"));
actor.AttemptsTo(Wait.Until(Appearance.Of(ResultPage.ResultLinks), IsEqualTo.True()));
77. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
actor.AttemptsTo(SearchDuckDuckGo.For("panda"));
actor.AttemptsTo(Wait.Until(Appearance.Of(ResultPage.ResultLinks), IsEqualTo.True()));
actor.AttemptsTo(QuitWebDriver.ForBrowser());
78. IActor actor = new Actor(name: "Andy", logger: new ConsoleLogger());
actor.Can(BrowseTheWeb.With(new ChromeDriver()));
actor.AttemptsTo(Navigate.ToUrl(SearchPage.Url));
actor.AskingFor(ValueAttribute.Of(SearchPage.SearchInput)).Should().BeEmpty();
actor.AttemptsTo(SearchDuckDuckGo.For("panda"));
actor.AttemptsTo(Wait.Until(Appearance.Of(ResultPage.ResultLinks), IsEqualTo.True()));
actor.AttemptsTo(QuitWebDriver.ForBrowser());