From 736d195760fdcd39c05e9d3ab58a3e01385fc024 Mon Sep 17 00:00:00 2001 From: Kamalpreet Kaur Date: Tue, 27 Dec 2022 18:24:23 +0530 Subject: [PATCH 1/6] init: add Cucumber with JUnit-4 runner sample --- README.md | 48 +++-------------- browserstack.yml | 14 +++-- build.gradle | 53 ------------------- pom.xml | 53 +++++++++++-------- .../RunWebDriverCucumberTests.java | 11 ++-- .../browserstack/stepdefs/StackDemoSteps.java | 3 +- src/test/resources/testng.xml | 9 ---- 7 files changed, 59 insertions(+), 132 deletions(-) delete mode 100644 build.gradle delete mode 100644 src/test/resources/testng.xml diff --git a/README.md b/README.md index 86c6a84..a566404 100644 --- a/README.md +++ b/README.md @@ -46,10 +46,14 @@ Understand how many parallel sessions you need by using our [Parallel Test Calcu org.apache.maven.plugins maven-surefire-plugin 3.0.0-M5 + + + org.apache.maven.surefire + surefire-junit47 + 3.0.0-M5 + + - - src/test/resources/testng.xml - -javaagent:${com.browserstack:browserstack-java-sdk:jar} @@ -57,43 +61,5 @@ Understand how many parallel sessions you need by using our [Parallel Test Calcu ``` -### Migrate from Vanilla Cucumber to use Testng Runner -* If you are using Vanilla Cucumber CLI, you can migrate to use TestNG Runner with BrowserStack using the below command : -``` -mvn archetype:generate -DarchetypeGroupId=com.browserstack -DarchetypeArtifactId=cucumber-testng-archetype -DarchetypeVersion=1.0 -DgroupId=com.browserstack -DartifactId=cucumber-testng-archetype -Dversion=1.0 -DinteractiveMode=false -``` -* Run your tests using `mvn test` -* To use specific `@CucumberOptions` in generated class `BrowserStackCucumberTestNgRunner`, refer - https://javadoc.io/static/io.cucumber/cucumber-testng/5.0.0-RC2/io/cucumber/testng/CucumberOptions.html - -## Using Gradle - -### Run sample build - -- Clone the repository -- Install dependencies `gradle build` -- To run the test suite having cross-platform with parallelization, run `gradle sampleTest` -- To run local tests, run `gradle sampleLocalTest` - -Understand how many parallel sessions you need by using our [Parallel Test Calculator](https://www.browserstack.com/automate/parallel-calculator?ref=github) - -### Integrate your test suite - -* Install dependencies `gradle build` -* Following are the changes required in `gradle.build` - - * Add `compileOnly 'com.browserstack:browserstack-java-sdk:latest.release'` in dependencies - * Fetch Artifact Information and add `jvmArgs` property in tasks *SampleTest* and *SampleLocalTest* : - ``` - def browserstackSDKArtifact = configurations.compileClasspath.resolvedConfiguration.resolvedArtifacts.find { it.name == 'browserstack-java-sdk' } - - task sampleTest(type: Test) { - useTestNG() { - dependsOn cleanTest - useDefaultListeners = true - suites "config/sample-test.testng.xml" - jvmArgs "-javaagent:${browserstackSDKArtifact.file}" - } - } - ``` - ## Notes * You can view your test results on the [BrowserStack Automate dashboard](https://www.browserstack.com/automate) diff --git a/browserstack.yml b/browserstack.yml index 68251bf..584066d 100644 --- a/browserstack.yml +++ b/browserstack.yml @@ -9,19 +9,27 @@ accessKey: YOUR_ACCESS_KEY # ====================== # Organizing your tests # ====================== -# Use `projectName`, `buildName`, `name` capabilities to organise your tests +# Use `projectName`, `buildName`, `name` capabilities to organize your tests # `name` is the name of your test sessions and is automatically picked from your # test name and doesn't need to be set manually when using BrowserStack SDK # `buildName` is used to name your CI/CD job or the execution of your test suite. # Ensure you add a dynamic identifier, like an incremental build number from your # CI/CD or timestamp at the end of every build; otherwise tests from different # executions will be grouped together on BrowserStack -buildName: browserstack-build-1 + # Use `projectName` to set the name of your project. Example, Marketing Website projectName: BrowserStack Samples +# Set `buildName` as the name of the job / testsuite being run +buildName: browserstack build +# `buildIdentifier` is a unique id to differentiate every execution that gets appended to +# buildName. Choose your buildIdentifier format from the available expressions: +# ${BUILD_NUMBER} (Default): Generates an incremental counter with every execution +# ${DATE_TIME}: Generates a Timestamp with every execution. Eg. 05-Nov-19:30 +# Read more about buildIdentifiers here -> https://www.browserstack.com/docs/automate/selenium/organize-tests + # Use `framework` to set the framework of your project. Example, testng, cucumber, cucumber-testng -framework: cucumber-testng +framework: cucumber-junit4 # ======================================= # Platforms (Browsers / Devices to test) diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 351b9e4..0000000 --- a/build.gradle +++ /dev/null @@ -1,53 +0,0 @@ -plugins { - id 'java' -} - -repositories { - mavenCentral() -} - -dependencies { - implementation 'org.seleniumhq.selenium:selenium-java:4.1.4' - testImplementation 'io.cucumber:cucumber-java:7.3.4' - testImplementation 'io.cucumber:cucumber-testng:7.3.4' - testImplementation 'io.cucumber:cucumber-core:7.3.4' - compileOnly 'com.browserstack:browserstack-java-sdk:latest.release' -} - -group = 'com.browserstack' -version = '1.0-SNAPSHOT' -description = 'cucumber-java-browserstack' -sourceCompatibility = '1.8' -targetCompatibility = '1.8' - -def browserstackSDKArtifact = configurations.compileClasspath.resolvedConfiguration.resolvedArtifacts.find { it.name == 'browserstack-java-sdk' } - -tasks.withType(JavaCompile) { - options.encoding = 'UTF-8' -} - -task sampleTest(type: Test) { - systemProperty "cucumber.publish.quiet", "true" - systemProperty "cucumber.features", "src/test/resources/features/test" - systemProperties System.getProperties() - useTestNG() { - dependsOn clean - useDefaultListeners = true - suites "src/test/resources/testng.xml" - jvmArgs "-javaagent:${browserstackSDKArtifact.file}" - } - scanForTestClasses = false -} - -task sampleLocalTest(type: Test) { - systemProperty "cucumber.publish.quiet", "true" - systemProperty "cucumber.features", "src/test/resources/features/localtest" - systemProperties System.getProperties() - useTestNG() { - dependsOn clean - useDefaultListeners = true - suites "src/test/resources/testng.xml" - jvmArgs "-javaagent:${browserstackSDKArtifact.file}" - } - scanForTestClasses = false -} diff --git a/pom.xml b/pom.xml index fdb9d51..4112ad2 100644 --- a/pom.xml +++ b/pom.xml @@ -14,20 +14,21 @@ UTF-8 1.8 1.8 - 7.4.1 + 7.8.1 7.4.0 4.1.4 1.0.6 1.1.1 LATEST + 2.20.0 + 1.8.0 - org.testng - testng - ${testng.version} - test + junit + junit + 4.13.2 io.cucumber @@ -37,7 +38,7 @@ io.cucumber - cucumber-testng + cucumber-junit ${cucumber.version} test @@ -47,18 +48,18 @@ ${selenium-java.version} test + + io.qameta.allure + allure-junit4 + 2.20.1 + test + com.browserstack browserstack-java-sdk ${browserstack-java-sdk.version} compile - - io.qameta.allure - allure-testng - 2.18.1 - test - @@ -87,13 +88,29 @@ org.apache.maven.plugins maven-surefire-plugin 3.0.0-M5 + + + org.apache.maven.surefire + surefire-junit47 + 3.0.0-M5 + + + org.aspectj + aspectjweaver + ${aspectj.version} + + - - src/test/resources/testng.xml - -javaagent:${com.browserstack:browserstack-java-sdk:jar} + -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar" + + + listener + io.qameta.allure.junit4.AllureJunit4 + + true @@ -111,9 +128,6 @@ maven-surefire-plugin 3.0.0-M5 - - src/test/resources/testng.xml - -javaagent:${com.browserstack:browserstack-java-sdk:jar} @@ -135,9 +149,6 @@ maven-surefire-plugin 3.0.0-M5 - - src/test/resources/testng.xml - -javaagent:${com.browserstack:browserstack-java-sdk:jar} diff --git a/src/test/java/com/browserstack/RunWebDriverCucumberTests.java b/src/test/java/com/browserstack/RunWebDriverCucumberTests.java index 3be242f..79788f1 100644 --- a/src/test/java/com/browserstack/RunWebDriverCucumberTests.java +++ b/src/test/java/com/browserstack/RunWebDriverCucumberTests.java @@ -1,6 +1,8 @@ package com.browserstack; -import io.cucumber.testng.*; +import io.cucumber.junit.Cucumber; +import io.cucumber.junit.CucumberOptions; +import org.junit.runner.RunWith; @CucumberOptions( glue = "com.browserstack.stepdefs", @@ -8,8 +10,11 @@ plugin = { "pretty", "html:reports/tests/cucumber/cucumber-pretty.html", - "testng:reports/tests/cucumber/testng/cucumber.xml", + "junit:reports/tests/cucumber/junit/cucumber.xml", "json:reports/tests/cucumber/json/cucumberTestReport.json" } ) -public class RunWebDriverCucumberTests extends AbstractTestNGCucumberTests {} + +@RunWith(Cucumber.class) +public class RunWebDriverCucumberTests { +} diff --git a/src/test/java/com/browserstack/stepdefs/StackDemoSteps.java b/src/test/java/com/browserstack/stepdefs/StackDemoSteps.java index 64a5f07..ea61615 100644 --- a/src/test/java/com/browserstack/stepdefs/StackDemoSteps.java +++ b/src/test/java/com/browserstack/stepdefs/StackDemoSteps.java @@ -7,6 +7,7 @@ import io.cucumber.java.en.Given; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; +import org.junit.Assert; import org.openqa.selenium.MutableCapabilities; import org.openqa.selenium.WebDriver; import org.openqa.selenium.remote.RemoteWebDriver; @@ -15,8 +16,6 @@ import java.net.URL; import java.util.HashMap; -import org.testng.Assert; - public class StackDemoSteps { private WebDriver driver; private HomePage homePage; diff --git a/src/test/resources/testng.xml b/src/test/resources/testng.xml deleted file mode 100644 index 28c168b..0000000 --- a/src/test/resources/testng.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - From 71a26eb44db648b3d6a4174250b47f4541ceedb3 Mon Sep 17 00:00:00 2001 From: Kamalpreet Kaur Date: Thu, 6 Jul 2023 17:43:54 +0530 Subject: [PATCH 2/6] chore: change sessionName --- README.md | 3 +-- pom.xml | 13 ------------- .../com/browserstack/RunWebDriverCucumberTests.java | 1 - src/test/resources/allure.properties | 1 - src/test/resources/features/localtest/Local.feature | 2 +- src/test/resources/features/test/StackDemo.feature | 2 +- 6 files changed, 3 insertions(+), 19 deletions(-) delete mode 100644 src/test/resources/allure.properties diff --git a/README.md b/README.md index a566404..c89c502 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cucumber Java Browserstack +# Cucumber-Junit4 Java Browserstack ![BrowserStack Logo](https://d98b8t1nnulk5.cloudfront.net/production/images/layout/logo-header.png?1469004780) [Cucumber JVM](https://cucumber.io/docs/reference/jvm) Integration with BrowserStack. @@ -12,7 +12,6 @@ - Install dependencies `mvn compile` - To run the test suite having cross-platform with parallelization, run `mvn test -P sample-test` - To run local tests, run `mvn test -P sample-local-test` -- To view Allure Reports, run `allure serve target/allure-results` Understand how many parallel sessions you need by using our [Parallel Test Calculator](https://www.browserstack.com/automate/parallel-calculator?ref=github) diff --git a/pom.xml b/pom.xml index 4112ad2..24fd125 100644 --- a/pom.xml +++ b/pom.xml @@ -48,12 +48,6 @@ ${selenium-java.version} test - - io.qameta.allure - allure-junit4 - 2.20.1 - test - com.browserstack browserstack-java-sdk @@ -103,14 +97,7 @@ -javaagent:${com.browserstack:browserstack-java-sdk:jar} - -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar" - - - listener - io.qameta.allure.junit4.AllureJunit4 - - true diff --git a/src/test/java/com/browserstack/RunWebDriverCucumberTests.java b/src/test/java/com/browserstack/RunWebDriverCucumberTests.java index 79788f1..1f0fb13 100644 --- a/src/test/java/com/browserstack/RunWebDriverCucumberTests.java +++ b/src/test/java/com/browserstack/RunWebDriverCucumberTests.java @@ -9,7 +9,6 @@ features = "src/test/resources/features/test", plugin = { "pretty", - "html:reports/tests/cucumber/cucumber-pretty.html", "junit:reports/tests/cucumber/junit/cucumber.xml", "json:reports/tests/cucumber/json/cucumberTestReport.json" } diff --git a/src/test/resources/allure.properties b/src/test/resources/allure.properties deleted file mode 100644 index 80b02dd..0000000 --- a/src/test/resources/allure.properties +++ /dev/null @@ -1 +0,0 @@ -allure.results.directory=target/allure-results diff --git a/src/test/resources/features/localtest/Local.feature b/src/test/resources/features/localtest/Local.feature index bf5edbf..ee12509 100644 --- a/src/test/resources/features/localtest/Local.feature +++ b/src/test/resources/features/localtest/Local.feature @@ -1,5 +1,5 @@ Feature: Verify Local test - Scenario: Navigate to Local App page + Scenario: BStack Local Test - Navigate to Local App page Given I am on the website 'http://bs-local.com:45454/' Then the page title should contain 'BrowserStack Local' diff --git a/src/test/resources/features/test/StackDemo.feature b/src/test/resources/features/test/StackDemo.feature index 9e3a2e5..f0df316 100644 --- a/src/test/resources/features/test/StackDemo.feature +++ b/src/test/resources/features/test/StackDemo.feature @@ -1,6 +1,6 @@ Feature: BrowserStack Demo - Scenario: Add product to cart + Scenario: BStack Sample Test - Add product to cart Given I am on the website 'https://www.bstackdemo.com' When I select a product and click on 'Add to cart' button Then the product should be added to cart From c2a8c5317b1707562b8fe27ca3f57481356d6244 Mon Sep 17 00:00:00 2001 From: Kamalpreet Kaur Date: Thu, 6 Jul 2023 17:51:43 +0530 Subject: [PATCH 3/6] update: browserstack.yml --- browserstack.yml | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/browserstack.yml b/browserstack.yml index ef52fd3..ab4b4ae 100644 --- a/browserstack.yml +++ b/browserstack.yml @@ -9,26 +9,19 @@ accessKey: YOUR_ACCESS_KEY # ====================== # BrowserStack Reporting # ====================== -# Use `projectName`, `buildName`, `name` capabilities to organize your tests -# `name` is the name of your test sessions and is automatically picked from your -# test name and doesn't need to be set manually when using BrowserStack SDK -# `buildName` is used to name your CI/CD job or the execution of your test suite. -# Ensure you add a dynamic identifier, like an incremental build number from your -# CI/CD or timestamp at the end of every build; otherwise tests from different -# executions will be grouped together on BrowserStack - -# Use `projectName` to set the name of your project. Example, Marketing Website -projectName: BrowserStack Samples - +# The following capabilities are used to set up reporting on BrowserStack: +# Set 'projectName' to the name of your project. Example, Marketing Website +projectName: BrowserStack Samples # Set `buildName` as the name of the job / testsuite being run -buildName: browserstack build +buildName: browserstack build # `buildIdentifier` is a unique id to differentiate every execution that gets appended to # buildName. Choose your buildIdentifier format from the available expressions: # ${BUILD_NUMBER} (Default): Generates an incremental counter with every execution # ${DATE_TIME}: Generates a Timestamp with every execution. Eg. 05-Nov-19:30 # Read more about buildIdentifiers here -> https://www.browserstack.com/docs/automate/selenium/organize-tests - -# Use `framework` to set the framework of your project. Example, testng, cucumber, cucumber-testng +buildIdentifier: '#${BUILD_NUMBER}' # Supports strings along with either/both ${expression} +# Set `framework` of your test suite. Example, `testng`, `cucumber`, `cucumber-testng` +# This property is needed to send test context to BrowserStack (test name, status) framework: cucumber-junit4 # ======================================= From 1532bc49c15cf4aec0a505922957ebe4de260765 Mon Sep 17 00:00:00 2001 From: Kamalpreet Kaur Date: Fri, 7 Jul 2023 12:11:40 +0530 Subject: [PATCH 4/6] chore: remove unnecessary deps --- pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pom.xml b/pom.xml index 24fd125..98f9846 100644 --- a/pom.xml +++ b/pom.xml @@ -88,11 +88,6 @@ surefire-junit47 3.0.0-M5 - - org.aspectj - aspectjweaver - ${aspectj.version} - From bbd8a048f25b73c25abb4d7cb1181eee1078d36c Mon Sep 17 00:00:00 2001 From: Kamalpreet Kaur Date: Mon, 10 Jul 2023 12:57:54 +0530 Subject: [PATCH 5/6] update: remove workflow since in master --- .github/workflows/maven-workflow-run.yml | 91 ------------------------ 1 file changed, 91 deletions(-) delete mode 100644 .github/workflows/maven-workflow-run.yml diff --git a/.github/workflows/maven-workflow-run.yml b/.github/workflows/maven-workflow-run.yml deleted file mode 100644 index e93bb3f..0000000 --- a/.github/workflows/maven-workflow-run.yml +++ /dev/null @@ -1,91 +0,0 @@ -# This job is to test different maven profiles in sdk branch again Pull Request raised -# This workflow targets Java with Maven execution - -name: Java SDK Test workflow for Maven on workflow_dispatch - -on: - workflow_dispatch: - inputs: - pull_request_number: - description: 'The pull request number to build' - required: true - -jobs: - comment-run: - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - max-parallel: 3 - matrix: - java: [ '8', '11', '17' ] - os: [ 'macos-latest', 'windows-latest', 'ubuntu-latest' ] - name: Cucumber Repo ${{ matrix.Java }} - ${{ matrix.os }} Sample - env: - BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} - BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} - - steps: - - uses: actions/checkout@v3 - with: - ref: refs/pull/${{ github.event.inputs.pull_request_number }}/head - - name: Fetch Commit SHA - run: | - git log -1 --format='%H' - echo "commit_sha=$(git log -1 --format='%H')" >> $GITHUB_ENV - echo "commit_sha=$(git log -1 --format='%H')" >> $env:GITHUB_ENV - - uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975 - id: status-check-in-progress - env: - job_name: Cucumber Repo ${{ matrix.Java }} - ${{ matrix.os }} Sample - with: - github-token: ${{ github.token }} - script: | - const result = await github.rest.checks.create({ - owner: context.repo.owner, - repo: context.repo.repo, - name: process.env.job_name, - head_sha: process.env.commit_sha, - status: 'in_progress' - }).catch((err) => ({status: err.status, response: err.response})); - console.log(`The status-check response : ${result.status} Response : ${JSON.stringify(result.response)}`) - if (result.status !== 201) { - console.log('Failed to create check run') - } - - name: Set up Java - uses: actions/setup-java@v3 - with: - distribution: 'temurin' - java-version: ${{ matrix.java }} - - name: Run mvn test - run: | - mvn compile - mvn test - - name: Run mvn profile sample-local-test - run: | - mvn compile - mvn test -P sample-local-test - - name: Run mvn profile sample-test - run: | - mvn compile - mvn test -P sample-test - - if: always() - uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975 - id: status-check-completed - env: - conclusion: ${{ job.status }} - job_name: Cucumber Repo ${{ matrix.Java }} - ${{ matrix.os }} Sample - with: - github-token: ${{ github.token }} - script: | - const result = await github.rest.checks.create({ - owner: context.repo.owner, - repo: context.repo.repo, - name: process.env.job_name, - head_sha: process.env.commit_sha, - status: 'completed', - conclusion: process.env.conclusion - }).catch((err) => ({status: err.status, response: err.response})); - console.log(`The status-check response : ${result.status} Response : ${JSON.stringify(result.response)}`) - if (result.status !== 201) { - console.log('Failed to create check run') - } From 2fc8449fc840abed4f4fc486e49823ff357943b0 Mon Sep 17 00:00:00 2001 From: Kamalpreet Kaur Date: Thu, 13 Jul 2023 15:49:47 +0530 Subject: [PATCH 6/6] update: get userName and accessKey from browserstack.yml to run it w/o SDK --- .../browserstack/stepdefs/StackDemoSteps.java | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/browserstack/stepdefs/StackDemoSteps.java b/src/test/java/com/browserstack/stepdefs/StackDemoSteps.java index 5ad2104..5ef5537 100644 --- a/src/test/java/com/browserstack/stepdefs/StackDemoSteps.java +++ b/src/test/java/com/browserstack/stepdefs/StackDemoSteps.java @@ -11,23 +11,38 @@ import org.openqa.selenium.MutableCapabilities; import org.openqa.selenium.WebDriver; import org.openqa.selenium.remote.RemoteWebDriver; +import org.yaml.snakeyaml.Yaml; import java.net.MalformedURLException; import java.net.URL; -import java.util.HashMap; +import java.io.File; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.*; public class StackDemoSteps { private WebDriver driver; private HomePage homePage; + public static String userName, accessKey; + public static Map browserStackYamlMap; + public static final String USER_DIR = "user.dir"; + + public StackDemoSteps() { + File file = new File(getUserDir() + "/browserstack.yml"); + this.browserStackYamlMap = convertYamlFileToMap(file, new HashMap<>()); + } + @Before public void setUp() throws MalformedURLException { MutableCapabilities capabilities = new MutableCapabilities(); HashMap bstackOptions = new HashMap<>(); - bstackOptions.putIfAbsent("source", "cucumber-java:sample-master:v1.2"); + userName = System.getenv("BROWSERSTACK_USERNAME") != null ? System.getenv("BROWSERSTACK_USERNAME") : (String) browserStackYamlMap.get("userName"); + accessKey = System.getenv("BROWSERSTACK_ACCESS_KEY") != null ? System.getenv("BROWSERSTACK_ACCESS_KEY") : (String) browserStackYamlMap.get("accessKey"); + bstackOptions.putIfAbsent("source", "cucumber-java:sample-cucumber-junit4:v1.0"); capabilities.setCapability("bstack:options", bstackOptions); driver = new RemoteWebDriver( - new URL("https://hub.browserstack.com/wd/hub"), capabilities); + new URL(String.format("https://%s:%s@hub.browserstack.com/wd/hub", userName , accessKey)), capabilities); homePage = new HomePage(driver); } @@ -60,4 +75,20 @@ public void teardown(Scenario scenario) throws Exception { Thread.sleep(2000); driver.quit(); } + + private String getUserDir() { + return System.getProperty(USER_DIR); + } + + private Map convertYamlFileToMap(File yamlFile, Map map) { + try { + InputStream inputStream = Files.newInputStream(yamlFile.toPath()); + Yaml yaml = new Yaml(); + Map config = yaml.load(inputStream); + map.putAll(config); + } catch (Exception e) { + throw new RuntimeException(String.format("Malformed browserstack.yml file - %s.", e)); + } + return map; + } }