czwartek, 14 marca 2019

SpecFlow with Coypu and custom IWebDriver for Coypu SessionConfiguration

Using Coypu with SpecFlow might have some limitations. Sometimes there is need to use driver with options or capabilities. Coypu gives possibility to customise web drivers with SessionConfiguration class.

Template

Example of Coypu custom web driver configurations is prepared in specflow-coypu-custom-webdriver template:

Custom Coypu driver configuration

To customise, for example, chrome driver, create class like below:

public class CustomChromeWebDriver : SeleniumWebDriver
    {
        public CustomChromeWebDriver(Browser browser) : base(CustomProfile(), browser)
        {
        }

        private static IWebDriver CustomProfile()
        {
            ChromeOptions chromeOptions = new ChromeOptions();
            chromeOptions.AddArguments("test-type");
            chromeOptions.AddArguments("--disable-extensions");

            return new ChromeDriver(chromeOptions);
        }
    }

Use name of created class for 'Driver' declaration in Coypu session configuration like below:

var sessionConfigurationForChrome = new SessionConfiguration()
{
Driver = typeof(CustomChromeWebDriver),
Browser = Coypu.Drivers.Browser.Chrome,
AppHost = "https://specflow.org/", // whatever url you want
Timeout = TimeSpan.FromSeconds(2)
};
browser = new BrowserSession(sessionConfigurationForChrome);
browser.MaximiseWindow();

Specflow-coypu-custom-webdriver template has BrowserSessionManager class to manage custom drivers for chrome, firefox, internet explorer and headless mode for chrome and firefox.

Custom RemoteWebDriver configuration

If you need to use RemoteWebDriver for running tests, in custom web driver classes replace IWebDriver to RemoteWebDriver (there might be also necessity to add option for running tests locally).

wtorek, 12 marca 2019

SpecFlow with Selenium IWebDriver manager

Specflow-webdriver-manager template uses Selenium IWebDriver for running browsers.

Template

Template you will find on GitHub:
https://github.com/bazylMN/specflow-webdriver-manager

WebDriverManager for browsers

Choice between browsers is managed by 'GetDriver()' method in WebDriverManager class:

public IWebDriver GetDriver()
        {
            var browserType = TestContext.Parameters["BROWSER"];
            switch (browserType)
            {
                case "CHROME":
                    webDriver = new ChromeDriver();
                    break;

                case "CHROMEHEADLESS":
                    ChromeOptions chromeOptions = new ChromeOptions();
                    chromeOptions.AddArguments("headless");
                    webDriver = new ChromeDriver(chromeOptions);
                    break;

                case "INTERNETEXPLORER":
                    webDriver = new InternetExplorerDriver();
                    break;

                case "FIREFOX":
                    webDriver = new FirefoxDriver();
                    break;

                case "FFHEADLESS":
                    FirefoxOptions firefoxOptions = new FirefoxOptions();
                    firefoxOptions.AddArguments("--headless");
                    webDriver = new FirefoxDriver(firefoxOptions);
                    break;

                default:
                    webDriver = new ChromeDriver();
                    break;
            }
            return webDriver;
        }

Commands for running particular browser

Default browser is Chrome, but you can choose Firefox, Internet Explorer or headless mode for Chrome and Firefox, using commands:

nunit3-console specflow-webdriver-manager\bin\Debug\specflow-webdriver-manager.dll --params:BROWSER=FIREFOX --work=NUnitTestResult --out=NUnitTestResult.txt --result=NUnitTestResult.xml

nunit3-console specflow-webdriver-manager\bin\Debug\specflow-webdriver-manager.dll --params:BROWSER=INTERNETEXPLORER --work=NUnitTestResult --out=NUnitTestResult.txt --result=NUnitTestResult.xml

nunit3-console specflow-webdriver-manager\bin\Debug\specflow-webdriver-manager.dll --params:BROWSER=CHROMEHEADLESS --work=NUnitTestResult --out=NUnitTestResult.txt --result=NUnitTestResult.xml

nunit3-console specflow-webdriver-manager\bin\Debug\specflow-webdriver-manager.dll --params:BROWSER=FFHEADLESS --work=NUnitTestResult --out=NUnitTestResult.txt --result=NUnitTestResult.xml

Instruction

Instruction of usage specflow-webdriver-manager template is placed in README.md file.

SpecFlow with Coypu and Coypu BrowserSession manager

SpecFlow UI tests might be run with Selenium IWebDriver or, you might use Coypu framework (https://github.com/featurist/coypu).
With Coypu you can manage browsers and interact with elements on page. After Coypu description:
"If your tests are littered with sleeps, retries, complex XPath expressions and IDs dug out of the source with browser developer tools then Coypu might help."

Template

Specflow-coypu template with Coypu BrowserSession manager you will find on GitHub:

Coypu configuration for browsers

Choice between browsers is managed by 'GetBrowser()' method in BrowserSessionManager class:

public BrowserSession GetBrowser()
        {
            if (browser != null)
                return browser;

            var sessionConfiguration = new SessionConfiguration()
            {
                Browser = GetBrowserName(),
                AppHost = "https://specflow.org/", // whatever url you want
                Timeout = TimeSpan.FromSeconds(2)
            };
            browser = new BrowserSession(sessionConfiguration);
            browser.MaximiseWindow();

            return browser;
        }

private Browser GetBrowserName()
        {
            var browserType = TestContext.Parameters["BROWSER"];
            switch (browserType)
            {
                case "CHROME":
                    browserName = Coypu.Drivers.Browser.Chrome;
                    break;

                case "INTERNETEXPLORER":
                    browserName = Coypu.Drivers.Browser.InternetExplorer;
                    break;

                case "FIREFOX":
                    browserName = Coypu.Drivers.Browser.Firefox;
                    break;

                default:
                    browserName = Coypu.Drivers.Browser.Chrome;
                    break;
            }
            return browserName;
        }

Comands for running particular browser

Default browser in template is Chrome, but you can choose Firefox or Internet Explorer, using command:

nunit3-console specflow-coypu\bin\Debug\specflow-coypu.dll --params:BROWSER=FIREFOX --work=NUnitTestResult --out=NUnitTestResult.txt --result=NUnitTestResult.xml

nunit3-console specflow-coypu\bin\Debug\specflow-coypu.dll --params:BROWSER=INTERNETEXPLORER --work=NUnitTestResult --out=NUnitTestResult.txt --result=NUnitTestResult.xml

Instruction

Instruction of usage is placed in README.md file.

wtorek, 19 lutego 2019

[QUICK TIP] SpecFlow/Visual Studio: how to handle with error "The geckodriver.exe file does not exist in the current directory or in a directory on the PATH environment variable"

At the start of work with SpecFlow framework in Visual Studio, you might get error like above, while running first test, which needs to initialise browser.

After adding driver .exe file to your testing project (for example chromedriver.exe, geckodriver.exe), in Visual Studio it is needed to change properties of .exe file.

Simply change "Copy to Output Directory" to "Copy always".



środa, 13 lutego 2019

Cucumber-java with Cucumber Spring, Selenide and Selenium WebDriver

Cucumber tests for web automated testing might be run with default selenide configuration- there is no need to configure custom web driver manager. 

This post is not for you, if you do not need custom web driver. Stay with selenide configuration (it also might be customised, see post: "Cucumber-java with custom Selenide configuration").

If you want to use Selenium WebDriver to manage browsers in tests project, this post is right for you.

Template

Whole template for cucmber-java-webdriver-manager you will find here: 

Instruction

There is an instruction attached to project, how to work with template, so here I do not write about setting up cucumber template. Read README.md file.

Test runner

Framework test runner is placed in CucumberRunner class:

@RunWith(Cucumber.class)
@CucumberOptions(
        glue={"cucumber.glue.hooks", 
              "cucumber.glue.steps", 
              "com.foreach.cuke"},
        features="src/test/resources/features",
        plugin={"pretty", "html:target/html"},
        monochrome=true)
@ContextConfiguration
@ComponentScan("classpath:cucumber.glue")
public class CucumberRunner {
}

In annotation @CucumberOptions, in 'glue' option there is 'com.foreach.cuke' phrase. It is necessary, when you run tests with Cucumber-java runner configuration. Edit your 'Run' configuration in IntelliJ: you should remove line 'cucumber.api.spring ' in 'Glue' row and paste 'com.foreach.cuke' instead (it prevents Spring TransactionDefinition error when tests are running). 
Both annotations: @ContextConfiguration and @ComponentScan are related to dependency injection with Spring.


Spring

As dependency injection template is using cucumber-spring library (with spring-context and spring-test libraries), so in class above you see annotations: @ContextConfiguration and @ComponentScan. Also in project there are another annotations, which are necessary for Spring and dependency injection: @Component and @Autowired (used in steps classes, page object classes and all classes, where dependency injection is needed).

@Autowired annotation used with field/ properties replaces common dependency injection:

@Autowired 
private NavigationPageObjects navigationPageObjects;

Common dependency injection looks like:

private NavigationPageObjects navigationPageObjects;
public NavigationPageSteps(NavigationPageObjects navigationPageObjects) {
    this.navigationPageObjects = navigationPageObjects;
}

With Spring dependency injection ends with two annotations, in this case one for class (@Component), second for field/properties (@Autowired).

Selenium WebDriver

Browsers management is dealed with WebDriverManager class. Simple switch/ case statement in method 'getWebDriver()' manages type of browser, which is chosen to automated testing:

 @PostConstruct
    public WebDriver getWebDriver(){
        String currentWebDriver = System.getProperty("browser", "");
        switch(currentWebDriver) {
            case ("chrome"):
                System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
                webDriver = new ChromeDriver();
                break;
            case ("firefox"):
                System.setProperty("webdriver.gecko.driver", "geckodriver.exe");
                FirefoxOptions firefoxOptions = new FirefoxOptions();
                firefoxOptions.setCapability("marionette", true);
                webDriver = new FirefoxDriver(firefoxOptions);
                break;
            case ("chromeHeadless"):
                System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
                ChromeOptions chromeHeadless = new ChromeOptions();
                chromeHeadless.setHeadless(true);
                webDriver = new ChromeDriver(chromeHeadless);
                break;
            case ("iexplorer"):
                System.setProperty("webdriver.ie.driver", "IEDriverServer.exe");
                DesiredCapabilities capabilitiesIE = DesiredCapabilities.internetExplorer();
 capabilitiesIE.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
                webDriver = new InternetExplorerDriver(capabilitiesIE);
                break;
            case ("edge"):
                System.setProperty("webdriver.edge.driver", "MicrosoftWebDriver.exe");
                webDriver = new EdgeDriver();
                break;
            case ("opera"):
                System.setProperty("webdriver.opera.driver", "operadriver.exe");
                webDriver = new OperaDriver();
                break;
            default:
                System.getProperty("browser", "chrome");
                System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
                webDriver = new ChromeDriver();
                break;
        }
        return webDriver;
    }

With @PostConstruct annotation Selenium WebDriver is initialised (with method 'getWebDriver()'). Default browser is sat to chrome, different browser is pointed by '-Dbrowser=' parameter before tests start running.

@PreDestroy
public void closeSession(){
webDriver.manage().deleteAllCookies();
webDriver.close();
webDriver.quit();
}

With @PreDestroy annotation Selenium WebDriver ends related processes.

Steps

Steps from scenarios are resolved in  NavigationPageSteps class.

public class NavigationPageSteps implements En {

    @Autowired
    private NavigationPageObjects navigationPageObjects;
    @Autowired
    private NavigationPageStepsAssertions assertions;

    @Given("I go to {string} page")
    public void iGoToPage(String urlName){
        navigationPageObjects.getPage(urlName);
   }

    @Then("I should be on {string} page")
    public void iShouldBeOnPage(String name){
        String currentPage = navigationPageObjects.getCurrentUrl();
        assertions.assertPageIsCorrect(currentPage, name);
    }
}

In steps class there are invoked only method from page objects classes (or assertions classes).

Selenide

Template is prepared for using Selenide library. In page object classes simply create methods and use Selenide to find elements or take actions. More about Selenide: https://selenide.org/.

niedziela, 13 stycznia 2019

[QUICK TIP] How to handle with error "Application was unable to start correctly (0xc000007b) while starting IntelliJ

Nice morning. First coffee. Starting Intellij. Oops.
 "Application was unable to start correctly (0xc000007b). (...)".
Hmm. Yesterday there was windows update with some protection issues. Hmm.
Quick google search. Many advices, mainly for interrupting games starting. Hmm.

Before you launch system recovery, try to add exception in "Exploit Protecion" function in windows defender for idea64.exe or idea.exe with turned off protection option/options. Run once again IntelliJ.
In my issue it helped.
System recovery also helped. Shortly. Until the next windows update.

Go to:

Windows Defender Security Center  App & browser control  Exploit protection settings  Program settings  Add program to customise  Add by program name -> type program name (idea64.exe)   Override system settings   Turn off setting/ settings  Apply

środa, 12 grudnia 2018

[QUICK TIP] Cucumber-java: how to configure reports for running tests locally in IDE (IntelliJ)

Sometimes, you need to run tests locally in your IDE. Having two kinds of reports (temporary and saved in file) is possible by configuring both console and "file" reports plugins.
One type of report is temporary console output. 
It needs "org.jetbrains.plugins.cucumber.java.run.CucumberJvm3SMFormatter" plugin ("Cucumber for java") to work fine. Its configuration is set in "Cucumber java" configuration runner after scenario or feature was run, in "Program arguments" row:

 --plugin org.jetbrains.plugins.cucumber.java.run.CucumberJvm3SMFormatter.

You can find it as follow:

Run  Edit Configurations → Cucumber java → name of test → Program arguments

Second type of report is "file" report.
It needs additionally configuration, when tests are running with context menu, not running directly runner class.
Its configuration you set in "Cucumber java" configuration runner after scenario or feature was run (or in cucumber runner template), in "Program arguments" row together with "CucumberJvm3SMFormatter" plugin. Simply type:

"--plugin pretty --plugin html:target/html"

All configuration in "Program arguments" row looks like below:

--plugin org.jetbrains.plugins.cucumber.java.run.CucumberJvm3SMFormatter --plugin pretty --plugin html:target/html"

Report is created in "target" directory as html report with "pretty" (default for Cucumber) formatter plugin. You also get formatted test output in console.

poniedziałek, 10 grudnia 2018

[QUICK TIP] IntelliJ: how to import gradle project when no gradle installed

If you have to import gradle project to IntelliJ and no gradle is installed in system, you can visit gradle home page to get library or allow IntelliJ does the work with installing gradle.
Before importing your target project, you can create temporary gradle project with IntelliJ: simply run IntelliJ, choose "Create new project" and select "Gradle" as type of project.

After temporary gradle project was created, you can import to IntelliJ your target gradle project (temporary one is not needed any more, so delete it).

wtorek, 4 grudnia 2018

[QUICK TIP] Visual Studio: how to resolve lack of references

Lack of reference usually happens, when you import project into IDE or when you switch to branch with some changes.
In Visual Studio you can use NuGet to get necessary libraries/packages.
One way is using general NuGet manager:

Tools  NuGet Package Manager  Manage NuGet Packages for Solution

Another way is using NuGet for particular project in your solution:

[Solution Explorer]  expand solution  expand project → References → context menu → Manage NuGet Packages

Missing references you can browse by name and install in chosen project.
After reference was installed, refresh project tree and build solution/project.


wtorek, 3 lipca 2018

Cucumber-java and enums

For reusing steps with different values as variables you might simply use enum class. you might of course use switch statement, but where is creativness here?

Feature file

Feature file looks as below:

Feature: As a user i want to visit cucumber page
  Scenario: Visit cucumber as first page and wp as second page
    Given I go to "cucumber" page
      Then I should be on "https://cucumber.io/" page
      When I go to "WP" page
      Then I should be on "https://www.wp.pl/" page

Enum class

Your enum class looks as below:

public enum UrlEnum{

    CUCUMBER("https://cucumber.io/"),
    WP("http://wp.pl"),
    ONET("http://onet.pl");

    public final String urlName;

    UrlEnum(String urlName) {
        this.urlName = urlName;
    }

    public static String getTranslatedEnum(String url) {
        UrlEnum nameToTranslate = UrlEnum.valueOf(url.toUpperCase());
        return nameToTranslate.toString();
    }

    @Override    public String toString() {
        return urlName;
    }
}

Enum class UrlEnum keeps url's strings and with method "getTranslatedEnum(urlName)" you might get value of enum's name- which is passed in "String url" from feature step.

Step in steps class

Step in steps class looks as below:

 @Given("I go to {string} page")
 public void iGoToPage(String urlName){
     urlToGo = UrlEnum.getTranslatedEnum(urlName);
     navigationPageObjects.getPage(urlToGo);
}

In project there might be many enum classes, which keep different categories.

Template

Whole template for "Cucumber-java-enums" you find on github: 
https://github.com/bazylMN/cucumber-java-enum.

Instruction

There is an instruction attached to project, how to work with template, so here I do not write about setting up template. Read README.md file.

Project works as template for cucumber-java framework. It is initial configuration for running tests with Cucumber-java with simple test. All you need is customise it, adding scenarios, steps, page objects and enums.