Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSTest with SDK #2

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
405 changes: 405 additions & 0 deletions .gitignore

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions Android/.config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"browserstack-sdk": {
"version": "1.13.8",
"commands": [
"browserstack-sdk"
]
}
}
}
24 changes: 24 additions & 0 deletions Android/Android.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="coverlet.collector" Version="3.2.0" />
<PackageReference Include="BrowserStackLocal" Version="2.3.1" />
<PackageReference Include="Appium.WebDriver" Version="4.4.5" />
<PackageReference Include="DotNetSeleniumExtras.WaitHelpers" Version="3.11.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="BrowserStack.TestAdapter" Version="0.10.8" />
</ItemGroup>

</Project>
23 changes: 23 additions & 0 deletions Android/BrowserstackMSTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Android;

public class BrowserstackMSTest
{
public AndroidDriver<AndroidElement>? driver;

public BrowserstackMSTest() { }

[TestInitialize]
public void TestSetup()
{
AppiumOptions appiumOptions = new AppiumOptions();
driver = new AndroidDriver<AndroidElement>(new Uri("http://127.0.0.1:4723/wd/hub"), appiumOptions);
}

[TestCleanup]
public void TestTeardown()
{
if (driver != null)
driver.Quit();
}
}

Binary file added Android/LocalSample.apk
Binary file not shown.
38 changes: 38 additions & 0 deletions Android/LocalTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
using System.Collections.ObjectModel;

namespace Android;

[TestClass]
public class LocalTest : BrowserstackMSTest
{

public LocalTest() { }

[TestMethod]
public void LocalNetworkTest()
{
if (driver == null)
throw new Exception("Could not run tests. Driver not initialised");

var _ = driver.PageSource;
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));

var testActionId = By.Id("com.example.android.basicnetworking:id/test_action");
AndroidElement testActionElement = (AndroidElement)wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(testActionId));
testActionElement.Click();
Thread.Sleep(5000);

_ = driver.PageSource;

ReadOnlyCollection<AndroidElement> textviewElements = driver.FindElementsByClassName("android.widget.TextView");
string text = textviewElements.Last().Text;

Assert.IsTrue(text.Contains("The active connection is wifi"));
Assert.IsTrue(text.Contains("Up and running"));

driver.ExecuteScript("browserstack_executor: { \"action\": \"setSessionStatus\", \"arguments\": { \"status\": \"passed\", \"reason\": \"Test Passed!\"} }");
}
}

39 changes: 39 additions & 0 deletions Android/SingleTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Collections.ObjectModel;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;

namespace Android;

[TestClass]
public class SingleTest : BrowserstackMSTest
{
public SingleTest() { }

[TestMethod]
public void SearchTest()
{
if (driver == null)
throw new Exception("Could not run tests. Driver not initialised");

var _ = driver.PageSource;
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));

var searchElementId = MobileBy.AccessibilityId("Search Wikipedia");
AndroidElement searchElement = (AndroidElement)wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(searchElementId));
searchElement.Click();
Thread.Sleep(2000);

_ = driver.PageSource;

wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
var insertTextElementId = By.Id("org.wikipedia.alpha:id/search_src_text");
AndroidElement insertTextElement = (AndroidElement)wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(insertTextElementId));
insertTextElement.SendKeys("BrowserStack");
Thread.Sleep(5000);

ReadOnlyCollection<AndroidElement> allProductsName = driver.FindElements(By.ClassName("android.widget.TextView"));
Assert.IsTrue(allProductsName.Count > 0);

driver.ExecuteScript("browserstack_executor: { \"action\": \"setSessionStatus\", \"arguments\": { \"status\": \"passed\", \"reason\": \"Test Passed!\"} }");
}
}
3 changes: 3 additions & 0 deletions Android/Usings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
global using Microsoft.VisualStudio.TestTools.UnitTesting;
global using OpenQA.Selenium.Appium;
global using OpenQA.Selenium.Appium.Android;
Binary file added Android/WikipediaSample.apk
Binary file not shown.
69 changes: 69 additions & 0 deletions Android/browserstack.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# =============================
# Set BrowserStack Credentials
# =============================
# Add your BrowserStack userName and acccessKey here or set BROWSERSTACK_USERNAME and
# BROWSERSTACK_ACCESS_KEY as env variables
userName: BROWSERSTACK_USERNAME
accessKey: BROWSERSTACK_ACCESS_KEY

# ======================
# BrowserStack Reporting
# ======================
# 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 `name` to set the session name
name: BStack android test
# 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
buildIdentifier: '#${BUILD_NUMBER}' # Supports strings along with either/both ${expression}

source: mstest:appium-sample-sdk:v1.0

# Set `app` to define the app that is to be used for testing.
# It can either take the id of any uploaded app or the path of the app directly.
app: ./WikipediaSample.apk
# app: ./LocalSample.apk #For running local tests

# =======================================
# Platforms (Browsers / Devices to test)
# =======================================
# Platforms object contains all the browser / device combinations you want to test on.
# Entire list available here -> (https://www.browserstack.com/list-of-browsers-and-platforms/automate)

platforms:
- deviceName: Samsung Galaxy S22 Ultra
osVersion: 12.0
platformName: android
- deviceName: OnePlus 11R
osVersion: 13.0
platformName: android
- deviceName: Google Pixel 6 Pro
osVersion: 12.0
platformName: android

# ==========================================
# BrowserStack Local
# (For localhost, staging/private websites)
# ==========================================
# Set browserStackLocal to true if your website under test is not accessible publicly over the internet
# Learn more about how BrowserStack Local works here -> https://www.browserstack.com/docs/automate/selenium/local-testing-introduction
browserstackLocal: true # <boolean> (Default false)
#browserStackLocalOptions:
#Options to be passed to BrowserStack local in-case of advanced configurations
# localIdentifier: # <string> (Default: null) Needed if you need to run multiple instances of local.
# forceLocal: true # <boolean> (Default: false) Set to true if you need to resolve all your traffic via BrowserStack Local tunnel.
# Entire list of arguments available here -> https://www.browserstack.com/docs/automate/selenium/manage-incoming-connections

# ===================
# Debugging features
# ===================
debug: false # <boolean> # Set to true if you need screenshots for every selenium command ran
networkLogs: false # <boolean> Set to true to enable HAR logs capturing
consoleLogs: errors # <string> Remote browser's console debug levels to be printed (Default: errors)
# Available options are `disable`, `errors`, `warnings`, `info`, `verbose` (Default: errors)
82 changes: 80 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,80 @@
# mstest-appium-app-browserstack
Sample Repo for running Appium Sessions using MSTest Framework
# MSTest-appium-app-browserstack

This sample elaborates the [MSTest](https://docs.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-mstest) Integration with BrowserStack.

<img src="assets/browserstack.png" width=30 height=30> <img src="assets/MSTest.png" width=50 height=25>

Note: SDK Support for MSTest Framework only works on Windows.

## Setup

### Installation Steps

1. Clone the repository.
2. Open the solution `mstest-appium-app-browserstack.sln` in Visual Studio.
3. Install dependencies using NuGet Package Manager:
```bash
dotnet restore
```
4. Build the solution

### Setup

1. Add your BrowserStack Username and Access Key to the `browserstack.yml` files in the Android/iOS project. You can get your browserstack credentials from [here](https://www.browserstack.com/accounts/profile/details)
```yml
userName: BROWSERSTACK_USERNAME
accessKey: BROWSERSTACK_ACCESS_KEY
```

2. Provide the path to your apk/ipa file in `browserstack.yml`.
```yml
app: ./WikipediaSample.apk
```

3. To run your test on multiple devices, update the devices list in `browserstack.yml`.
```yml
platforms:
- deviceName: Samsung Galaxy S22 Ultra
osVersion: 12.0
platformName: android
```

4. To run your tests using Browserstack Local. Update the `browserstack.yml` with the following key:
```yml
browserstackLocal: true # <boolean> (Default false)
```

### Running Tests

- To run tests, execute the following command:
```bash
dotnet test
```

- To run tests on Android/iOS, provide `<os>` to the below command. Where os can take either of two values: `Android` or `iOS`.
```bash
dotnet test <os>
```

- To run the single test, execute the following command:
```bash
dotnet test <os> --filter SingleTest
```

- To run local tests, execute the following command:
```bash
dotnet test <os> --filter LocalTest
```

Understand how many parallel sessions you need by using our [Parallel Test Calculator](https://www.browserstack.com/app-automate/parallel-calculator?ref=github)

## Notes
* You can view your test results on the [BrowserStack automate dashboard](https://www.browserstack.com/app-automate)
* To test on a different set of devices or build a set of appium capabilities, use our [Capability Builder](https://www.browserstack.com/app-automate/capabilities?tag=w3c)

## Additional Resources
* [Documentation for writing automate playwright test scripts in C#](https://www.browserstack.com/docs/app-automate/appium/getting-started/c-sharp)
* [Capability Builder for App Automate](https://www.browserstack.com/app-automate/capabilities)
* [Real Mobile devices for Appium testing on BrowserStack](https://www.browserstack.com/list-of-browsers-and-platforms/app_automate)
* [Using REST API to access information about your tests via the command-line interface](https://www.browserstack.com/docs/app-automate/api-reference/introduction)

Binary file added assets/MSTest.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/browserstack.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions iOS/.config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"version": 1,
"isRoot": true,
"tools": {}
}
Binary file added iOS/BStackSampleApp.ipa
Binary file not shown.
23 changes: 23 additions & 0 deletions iOS/BrowserstackMSTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace iOS;

public class BrowserstackMSTest
{
protected IOSDriver<IOSElement>? driver;

public BrowserstackMSTest() { }

[TestInitialize]
public void TestSetup()
{
AppiumOptions appiumOptions = new AppiumOptions();
driver = new IOSDriver<IOSElement>(new Uri("http://127.0.0.1:4723/wd/hub"), appiumOptions);
}

[TestCleanup]
public void TestTeardown()
{
if (driver != null)
driver.Quit();
}
}

Binary file added iOS/LocalSample.ipa
Binary file not shown.
33 changes: 33 additions & 0 deletions iOS/LocalTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;

namespace iOS;

[TestClass]
public class LocalTest : BrowserstackMSTest
{
[TestMethod]
public void LocalNetworkTest()
{
if (driver == null)
throw new Exception("Could not run tests. Driver not initialised");

var _ = driver.PageSource;
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));

var testButtonId = By.XPath("/XCUIElementTypeApplication/XCUIElementTypeWindow/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton/XCUIElementTypeStaticText");
IOSElement testButton = (IOSElement)wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(testButtonId));
testButton.Click();
Thread.Sleep(5000);

_ = driver.PageSource;

IOSElement textElement = driver.FindElementByXPath("/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeTextField");
string text = textElement.Text;

Assert.IsTrue(text.Contains("Up and running"));

driver.ExecuteScript("browserstack_executor: { \"action\": \"setSessionStatus\", \"arguments\": { \"status\": \"passed\", \"reason\": \"Test Passed!\"} }");
}
}

Loading