Skip to content

Commit 3dccf49

Browse files
update examples
1 parent ccc16d4 commit 3dccf49

File tree

8 files changed

+449
-201
lines changed

8 files changed

+449
-201
lines changed

.github/workflows/test.yml

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,72 @@
11
---
22
name: Tests
33

4-
on: push
4+
on:
5+
push:
6+
branches: [main, develop]
7+
pull_request:
8+
branches: [main]
59

610
jobs:
7-
tests:
8-
name: Unit Testing
9-
runs-on: windows-latest
11+
build-and-test:
12+
name: Build and Test
13+
runs-on: ubuntu-latest
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
test-category: [Basic, Parallel, BiDi]
18+
1019
steps:
11-
- uses: actions/[email protected]
12-
- run: dotnet test
20+
- name: Checkout code
21+
uses: actions/checkout@v4
22+
23+
- name: Setup .NET
24+
uses: actions/setup-dotnet@v4
25+
with:
26+
dotnet-version: '9.0.x'
27+
28+
- name: Restore dependencies
29+
run: dotnet restore
30+
31+
- name: Build
32+
run: dotnet build --no-restore --configuration Release
33+
34+
- name: Run tests
35+
run: |
36+
if [ "${{ matrix.test-category }}" == "Basic" ]; then
37+
dotnet test --no-build --configuration Release --logger trx --results-directory TestResults/ --filter "TestCategory!=Parallel&TestCategory!=BiDi"
38+
elif [ "${{ matrix.test-category }}" == "Parallel" ]; then
39+
dotnet test --no-build --configuration Release --logger trx --results-directory TestResults/ --filter "TestCategory=Parallel"
40+
else
41+
dotnet test --no-build --configuration Release --logger trx --results-directory TestResults/ --filter "TestCategory=BiDi"
42+
fi
1343
env:
1444
TESTINGBOT_KEY: ${{ secrets.TESTINGBOT_KEY }}
1545
TESTINGBOT_SECRET: ${{ secrets.TESTINGBOT_SECRET }}
46+
47+
- name: Upload test results
48+
uses: actions/upload-artifact@v4
49+
if: always()
50+
with:
51+
name: test-results-${{ matrix.test-category }}
52+
path: TestResults/
53+
54+
lint-and-analyze:
55+
name: Code Quality
56+
runs-on: ubuntu-latest
57+
58+
steps:
59+
- name: Checkout code
60+
uses: actions/checkout@v4
61+
62+
- name: Setup .NET
63+
uses: actions/setup-dotnet@v4
64+
with:
65+
dotnet-version: '9.0.x'
66+
67+
- name: Restore dependencies
68+
run: dotnet restore
69+
70+
- name: Build and analyze
71+
run: dotnet build --configuration Release --verbosity normal
1672

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,33 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
2-
3-
<PropertyGroup>
4-
<TargetFramework>net6.0</TargetFramework>
5-
<RootNamespace>NUnit_TestingBot_Sample</RootNamespace>
6-
<ImplicitUsings>enable</ImplicitUsings>
7-
<Nullable>enable</Nullable>
8-
9-
<IsPackable>false</IsPackable>
10-
</PropertyGroup>
11-
12-
<ItemGroup>
13-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
14-
<PackageReference Include="NUnit" Version="4.1.0" />
15-
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
16-
<PackageReference Include="NUnit.Analyzers" Version="4.0.1"><IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
17-
<PrivateAssets>all</PrivateAssets>
18-
</PackageReference>
19-
<PackageReference Include="coverlet.collector" Version="6.0.1"><IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
20-
<PrivateAssets>all</PrivateAssets>
21-
</PackageReference>
22-
<PackageReference Include="Selenium.WebDriver" Version="4.18.1" />
23-
</ItemGroup>
24-
25-
<ItemGroup>
26-
<None Remove="Selenium.WebDriver" />
27-
</ItemGroup>
28-
</Project>
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<RootNamespace>NUnit_TestingBot_Sample</RootNamespace>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
9+
<WarningsAsErrors />
10+
<WarningsNotAsErrors>NU1701</WarningsNotAsErrors>
11+
12+
<IsPackable>false</IsPackable>
13+
<IsTestProject>true</IsTestProject>
14+
</PropertyGroup>
15+
16+
<ItemGroup>
17+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
18+
<PackageReference Include="NUnit" Version="4.2.2" />
19+
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
20+
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
21+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
22+
<PrivateAssets>all</PrivateAssets>
23+
</PackageReference>
24+
<PackageReference Include="coverlet.collector" Version="6.0.2">
25+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
26+
<PrivateAssets>all</PrivateAssets>
27+
</PackageReference>
28+
<PackageReference Include="Selenium.WebDriver" Version="4.33.0" />
29+
<PackageReference Include="Selenium.Support" Version="4.33.0" />
30+
<PackageReference Include="FluentAssertions" Version="6.12.1" />
31+
</ItemGroup>
32+
33+
</Project>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<RunSettings>
3+
<RunConfiguration>
4+
<MaxCpuCount>4</MaxCpuCount>
5+
<ResultsDirectory>./TestResults</ResultsDirectory>
6+
</RunConfiguration>
7+
8+
<NUnit>
9+
<NumberOfTestWorkers>4</NumberOfTestWorkers>
10+
<DefaultTimeout>60000</DefaultTimeout>
11+
<WorkDirectory>./TestResults</WorkDirectory>
12+
<InternalTraceLevel>Info</InternalTraceLevel>
13+
<RandomSeed>1234567890</RandomSeed>
14+
<DefaultTestNamePattern>{c}.{m}</DefaultTestNamePattern>
15+
</NUnit>
16+
17+
<DataCollectionRunSettings>
18+
<DataCollectors>
19+
<DataCollector friendlyName="XPlat code coverage">
20+
<Configuration>
21+
<Format>opencover</Format>
22+
</Configuration>
23+
</DataCollector>
24+
</DataCollectors>
25+
</DataCollectionRunSettings>
26+
</RunSettings>
Lines changed: 102 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,128 @@
1-
using OpenQA.Selenium;
1+
using OpenQA.Selenium;
22
using OpenQA.Selenium.Chrome;
33
using OpenQA.Selenium.Firefox;
44
using OpenQA.Selenium.Remote;
55
using OpenQA.Selenium.Safari;
6+
using FluentAssertions;
67

78
namespace NUnit_TestingBot_Sample;
89

9-
public class ParallelTests
10+
[TestFixture("chrome", "latest", "Windows 10")]
11+
[TestFixture("firefox", "latest", "macOS Sequoia")]
12+
[Parallelizable(ParallelScope.Fixtures)]
13+
[Category("Parallel")]
14+
public class ParallelSeleniumTests
1015
{
11-
[TestFixture("chrome", "latest", "Windows 10")]
12-
[TestFixture("firefox", "latest", "SONOMA")]
13-
[Parallelizable(ParallelScope.Fixtures)]
14-
public class TbNUnit_ParallelTest
16+
private IWebDriver? _driver;
17+
private readonly string _browser;
18+
private readonly string _version;
19+
private readonly string _os;
20+
21+
public ParallelSeleniumTests(string browser, string version, string os)
1522
{
16-
private IWebDriver driver;
17-
private string browser;
18-
private string version;
19-
private string os;
23+
_browser = browser;
24+
_version = version;
25+
_os = os;
26+
}
27+
28+
[SetUp]
29+
public void SetUp()
30+
{
31+
var browserOptions = CreateBrowserOptions();
32+
var testingBotOptions = CreateTestingBotOptions();
33+
34+
browserOptions.AddAdditionalOption("tb:options", testingBotOptions);
2035

21-
public TbNUnit_ParallelTest(String browser, String version, String os)
36+
_driver = new RemoteWebDriver(
37+
new Uri("https://hub.testingbot.com/wd/hub"),
38+
browserOptions.ToCapabilities(),
39+
TimeSpan.FromSeconds(600));
40+
41+
_driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
42+
_driver.Manage().Window.Maximize();
43+
}
44+
45+
46+
[Test]
47+
[Parallelizable(ParallelScope.Self)]
48+
public void ShouldHandleSimpleFormInteraction()
49+
{
50+
_driver!.Navigate().GoToUrl("https://the-internet.herokuapp.com/login");
51+
52+
var usernameField = _driver.FindElement(By.Id("username"));
53+
var passwordField = _driver.FindElement(By.Id("password"));
54+
var loginButton = _driver.FindElement(By.ClassName("radius"));
55+
56+
usernameField.SendKeys("tomsmith");
57+
passwordField.SendKeys("SuperSecretPassword!");
58+
loginButton.Click();
59+
60+
var successMessage = _driver.FindElement(By.CssSelector(".flash.success"));
61+
successMessage.Text.Should().Contain("You logged into a secure area!");
62+
}
63+
64+
[TearDown]
65+
public void TearDown()
66+
{
67+
if (_driver == null) return;
68+
69+
var testPassed = TestContext.CurrentContext.Result.Outcome.Status ==
70+
NUnit.Framework.Interfaces.TestStatus.Passed;
71+
72+
try
2273
{
23-
this.browser = browser;
24-
this.version = version;
25-
this.os = os;
74+
((IJavaScriptExecutor)_driver).ExecuteScript($"tb:test-result={testPassed.ToString().ToLower()}");
2675
}
76+
catch (Exception ex)
77+
{
78+
TestContext.Out.WriteLine($"Failed to report test result: {ex.Message}");
79+
}
80+
finally
81+
{
82+
_driver.Quit();
83+
_driver.Dispose();
84+
}
85+
}
2786

28-
[SetUp]
29-
public void Init()
87+
private DriverOptions CreateBrowserOptions()
88+
{
89+
return _browser.ToLower() switch
3090
{
31-
DriverOptions browserOptions;
32-
if (this.browser == "firefox")
91+
"firefox" => new FirefoxOptions
3392
{
34-
browserOptions = new FirefoxOptions()
35-
{
36-
BrowserVersion = this.version,
37-
PlatformName = this.os
38-
};
39-
}
40-
else if (this.browser == "safari")
93+
BrowserVersion = _version,
94+
PlatformName = _os
95+
},
96+
"safari" => new SafariOptions
4197
{
42-
browserOptions = new SafariOptions()
43-
{
44-
BrowserVersion = this.version,
45-
PlatformName = this.os
46-
};
47-
}
48-
else
98+
BrowserVersion = _version,
99+
PlatformName = _os
100+
},
101+
_ => new ChromeOptions
49102
{
50-
browserOptions = new ChromeOptions()
51-
{
52-
BrowserVersion = this.version,
53-
PlatformName = this.os
54-
};
103+
BrowserVersion = _version,
104+
PlatformName = _os
55105
}
106+
};
107+
}
56108

57-
var tbOptions = new Dictionary<string, string>
58-
{
59-
["key"] = Environment.GetEnvironmentVariable("TESTINGBOT_KEY"),
60-
["secret"] = Environment.GetEnvironmentVariable("TESTINGBOT_SECRET"),
61-
["name"] = TestContext.CurrentContext.Test.Name,
62-
["selenium-version"] = "3.14.0"
63-
};
64-
65-
browserOptions.AddAdditionalOption("tb:options", tbOptions);
66-
67-
driver = new RemoteWebDriver(new Uri("https://hub.testingbot.com/wd/hub"), browserOptions.ToCapabilities(), TimeSpan.FromSeconds(600));
68-
}
109+
private Dictionary<string, object> CreateTestingBotOptions()
110+
{
111+
var key = Environment.GetEnvironmentVariable("TESTINGBOT_KEY");
112+
var secret = Environment.GetEnvironmentVariable("TESTINGBOT_SECRET");
69113

70-
[Test]
71-
public void GoogleTest()
114+
if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(secret))
72115
{
73-
driver.Navigate().GoToUrl("http://www.google.com");
74-
Assert.That(driver.Title, Is.EqualTo("Google"));
75-
IWebElement query = driver.FindElement(By.Name("q"));
76-
query.SendKeys("TestingBot");
77-
query.Submit();
116+
throw new InvalidOperationException(
117+
"TESTINGBOT_KEY and TESTINGBOT_SECRET environment variables must be set");
78118
}
79119

80-
[TearDown]
81-
public void CleanUp()
120+
return new Dictionary<string, object>
82121
{
83-
bool passed = TestContext.CurrentContext.Result.Outcome.Status == NUnit.Framework.Interfaces.TestStatus.Passed;
84-
try
85-
{
86-
// Logs the result to TestingBot
87-
((IJavaScriptExecutor)driver).ExecuteScript("tb:test-result=" + (passed ? "passed" : "failed"));
88-
}
89-
finally
90-
{
91-
// Terminates the remote webdriver session
92-
driver.Quit();
93-
driver.Dispose();
94-
}
95-
}
122+
["key"] = key,
123+
["secret"] = secret,
124+
["name"] = $"{TestContext.CurrentContext.Test.Name} ({_browser} on {_os})",
125+
["selenium-version"] = "4.27.0"
126+
};
96127
}
97128
}

0 commit comments

Comments
 (0)