Getting Started
Introduction
Atata Framework is a full-featured C#/.NET test automation framework built around a powerful context-driven architecture and session-based execution model. It provides an intuitive, fluent page object pattern for web UI testing, which remains its core capability, while Atata 4 expands beyond web UI automation into a universal, extensible testing ecosystem. Designed to minimize boilerplate, Atata enables clean, declarative test components using properties, attributes, and reusable building blocks. With customizable built-in logging, a unique event-driven trigger system, and a rich ecosystem of ready-to-use components, Atata provides a consistent foundation for building maintainable and scalable automated tests across different testing domains.
The framework is completely open-source and hosted on GitHub as Atata Framework organization under the Apache License 2.0. All framework libraries are published and available as NuGet packages.
Concepts
Overview
Core
The framework core consists of the following concepts:
- AtataContext - the core runtime representation of a test execution context in Atata.
- AtataContextBuilder - a fluent builder for configuring the
AtataContext.
- AtataContextBuilder - a fluent builder for configuring the
- AtataSession - a session within the
AtataContext. - Verification functionality
- Assertion -
.Should.*assertion. For example:UserName.Should.Be("John"). - Expectation -
.ExpectTo.*expectation, which produces a warning. - Waiting -
.WaitTo.*waiting for a certain condition. For example:Component.WaitTo.BeVisible().
- Assertion -
Web testing
- Components - classes that represent the most often used HTML components.
- Controls
- Page objects
- Control list
- Attributes
- Attributes of control search - basically, element locators,
like
[FindById],[FindByName],[FindByXPath], etc. - Trigger attributes - a functionality that is automatically executed in response to certain events on a particular component. For example, when a click on button occurs it may be defined that a wait should be executed.
- Behavior attributes - change the way how particular actions are executed.
For example, specify the click behavior for a specific button by adding
[ClickUsingScript]to perform the click using JavaScript, instead of defaultIWebElement.Click()way. - Settings attributes - set settings for control finding, culture, value format, etc.
- Attributes of control search - basically, element locators,
like
AtataContext
AtataContext is the central object that defines and manages the execution environment for a test or test suite in Atata,
bundling configuration, sessions, logging, state, events, artifacts, and lifecycle management into a single runtime context.
Conceptually
- It represents a test scope:
- Global scope.
- Namespace scope (supported in NUnit only).
- Test suite group (supported in Xunit only).
- Test suite/class.
- Individual test.
- Unscoped unit.
- It holds the state, resources, and behavior for that scope.
- It is created through
AtataContext.CreateBuilder(...)method and then built.
Main responsibilities
- Manage the current active context via
AtataContext.Current. - Track parent/child context hierarchy.
- Own sessions via
Sessions(including WebDriver sessions). - Provide logging and reporting abilities via
LogandReportproperties. - Manage artifacts.
- Store variables and state in hierarchical dictionaries.
- Record assertion results and test result status.
- Publish and subscribe to Atata events with
EventBus. - Handle lifecycle: initialization, activation, deinitialization.
Lifecycle
- Created and configured by
AtataContextBuildertogether with associated sessions. - Used throughout test execution.
- Disposed to deinitialize sessions, publish completion events, clean up artifacts, and finalize test results.
The lifecycle is managed automatically when you Atata with one of the packages: Atata.NUnit, Atata.Xunit.v3, Atata.MSTest.
Key properties
Scope— context scope type.ParentContext- parent context in the hierarchy.ChildContexts- collection of child contexts.Test— metadata for the test or suite.Id— unique context identifier.Sessions— collection of sessions associated with the context.Log— context-specific logging.Report— context-specific reporting interface.EventBus— event subscription/publish mechanism.Variables— context variables hierarchical dictionary.State— context state hierarchical dictionary.Artifacts/ArtifactsPath— artifact storage.
AtataSession
AtataSession is the framework-level abstraction for a running session (e.g., a browser/WebDriver session, ASP.NET Core web application session, or any test session)
that encapsulates session-specific state, logging, events and lifecycle within an AtataContext.
A session can be associated with a context, shared, borrowed, or managed from a pool, and it provides lifecycle support for initialization, disposal, and returning to its source context.
Typically, a session’s lifecycle aligns with the context’s lifecycle, but there are options to adjust this behavior, as detailed below.
Session borrowing
You can configure a single session at the test suite level and share it across all child tests, effectively reusing the same session. For UI testing, this means a single browser instance will be utilized for all tests in the suite. However, this approach has a key limitation: tests within such a suite must not run in parallel, but still can run in parallel with tests from other suites.
Session pool
A session pool allows you to manage reusable AtataSession instances efficiently.
When a context ends, the session is returned to the pool, making it available for reuse by other contexts.
The pool’s initial and maximum capacity are fully configurable.
You can define multiple pools, even for the same session type, by assigning unique names to each pool.
Typically, pools are configured at the global AtataContext level for optimal management.
Key properties
Id— unique session identifier.Name— optional session name.IsActive— whether the session is still active.Mode— the session mode.Context— the context the session is currently associated with.OwnerContext— the context in which the session was created.Log— session-specific logging.Report— session-specific reporting interface.EventBus— event subscription/publish mechanism.Variables— session variables hierarchical dictionary.State— session state hierarchical dictionary.
Artifacts
Artifacts (AtataContext.Artifacts) is the per-test/suite artifact storage location used to keep files generated during test execution organized and isolated.
It is intended for things such as logs, screenshots, downloaded files, reports, and any other output produced by the test.
By default, the folder is created under the global artifacts root and is derived from the current test/suite context, which makes it easy to locate artifacts for each run.
Artifacts structure
Here is how the Artifacts file structure looks for NUnit considering AtataContext is used at all levels (global, namespace, test suite, test):
📁 SubNamespace
▪ 📁 Suite1Tests
▪ ▪ 📁 Test1
▪ ▪ ▪ 📄 Trace.log
▪ ▪ 📁 Test2
▪ ▪ ▪ 📄 Trace.log
▪ ▪ 📄 Trace.log (test suite log)
▪ 📄 Trace.log (namespace log)
📁 Suite2Tests
▪ 📁 Test1
▪ ▪ 📄 Trace.log
▪ 📁 Test2
▪ ▪ 📄 Trace.log
▪ 📄 Trace.log (test suite log)
📄 Trace.log (global log)
AtataContext artifacts path properties
Artifactsto work with the directory as an AtataDirectorySubject.ArtifactsPathto get the full physical path.ArtifactsRelativePathto get the relative path.
AtataContext artifact-adding methods
AtataContext provides a small set of overloads for saving files into the current test’s artifacts folder. Each method:
- writes the file under the context’s artifacts directory;
- creates parent folders if needed;
- optionally prefixes the file name with a sequential
001-style number; - raises an artifact-added event;
- returns a
FileSubjectfor the created file.
Available overloads
AddArtifact(string relativeFilePathWithoutExtension, FileContentWithExtension fileContentWithExtension, in AddArtifactOptions options = default)AddArtifact(string relativeFilePath, byte[] fileBytes, in AddArtifactOptions options = default)AddArtifact(string relativeFilePath, string fileContent, in AddArtifactOptions options = default)AddArtifact(string relativeFilePath, string fileContent, Encoding encoding, in AddArtifactOptions options = default)AddArtifact(string relativeFilePath, Stream stream, in AddArtifactOptions options = default)
AddArtifactOptions properties
ArtifactType— a category such as a predefined type fromArtifactTypesor a custom value.ArtifactTitle— a human-readable title.PrependArtifactNumberToFileName— prefixes the file with a three-digit sequence number.
Logs
Atata provides a built-in logging system designed to capture structured test execution details, including component interactions, assertions, custom debug messages, etc.
The logging subsystem is managed primarily via AtataContext and configured through builders.
Log levels
Atata supports standard severity levels:
TraceDebugInfoWarnErrorFatal
Configuration
Log consumers are added during the AtataContextBuilder configuration phase.
The log consumers can be registered through the methods of LogConsumers property of AtataContextBuilder.
builder.LogConsumers.AddNLogFile();
builder.LogConsumers.AddNLogFile(x => x
.WithSectionEnd(LogSectionEndOption.Exclude)
.WithMinLevel(LogLevel.Info));
Writing custom log messages
Atata exposes logging methods directly through the public Log property of AtataContext or AtataSession;
or the protected Log property of UIComponent.
Context.Log.Debug("...");
Session.Log.Info("...");
In UI tests, you can also use the Report property of PageObject<TOwner>.
Go.To<SomePageObject>()
.Report.Info("...")
.Report.Step(
"Some step",
x => x.DoSomeAction());
Log sections
Atata supports nested log sections - hierarchical log blocks.
Context.Log.ExecuteSection(
new LogSection("Set up test data"),
() =>
{
// Actions executed inside this block are nested in output logs.
// ...
});
Log categories
Use ForCategory method of ILogManager to log messages with a specific category.
Context.Log.ForCategory("Custom category").Debug("Some message");
Context.Log.ForCategory<SomeClass>().Info("Some other message");
->
00:00:00.001 hDrP DEBUG [Custom category] Some message
00:00:00.001 hDrP INFO [SomeProject.UITests.SomeClass] Some other message
Category, at the moment, is not consumed in Atata itself, but it is available for custom purposes.
Log sources
Use ForSource method of ILogManager to log messages with a specific external source.
Context.Log.ForSource("Some source").Debug("Some message");
->
00:00:00.001 hDrP DEBUG {Some source} Some message
For example, browser logs are reported with “Browser” external source:
00:00:03.163 fj9J DEBUG {Browser} http://localhost:50549/browserlogs 14:12 "console debug log entry"
00:00:03.164 fj9J ERROR {Browser} http://localhost:50549/browserlogs 17:12 "console error log entry"
For large external logs, it might be useful to target external source logs to a separate log file, which is possible to do with NLog.
State
public StateHierarchicalDictionary State { get; } property is present in both AtataContext and AtataSession.
This property serves as a hierarchical object dictionary, allowing you to store objects at a higher level (e.g., global)
and retrieve them at a lower level (e.g., test).
This feature is particularly useful for managing complex test scenarios.
AtataContext.Global!.State["string key"] = "string value";
AtataContext.Global!.State.Set(new SomeObject(...));
//...
string stringValue = Context.State.Get<string>("string key");
SomeObject someObject = Context.State.Get<SomeObject>();
Packages
Atata Framework consists of a set of NuGet packages.
Main packages
- Atata (GitHub | NuGet) - is a core package, which provides base and main functionality for Atata testing.
- Atata.NUnit (GitHub | NuGet) - provides integration with NUnit testing framework.
- Atata.Xunit.v3 (GitHub | NuGet) - provides integration with xUnit v3 testing framework.
- Atata.MSTest (GitHub | NuGet) - provides integration with MSTest testing framework.
- Atata.Reqnroll.NUnit (GitHub | NuGet) - provides integration with Reqnroll+NUnit testing frameworks combination.
- Atata.NLog (GitHub | NuGet) - adds NLog logging to Atata.
- Atata.ExtentReports (GitHub | NuGet) - adds ExtentReports reporting to Atata.
- Atata.Testcontainers (GitHub | NuGet) - adds Docker container sessions to Atata using Testcontainers library.
- Atata.AspNetCore.v8 (GitHub | NuGet) - adds ASP.NET Core 8.0 sessions to Atata using WebApplicationFactory.
- Atata.AspNetCore.v9 (GitHub | NuGet) - adds ASP.NET Core 9.0 sessions to Atata using WebApplicationFactory.
- Atata.AspNetCore.v10 (GitHub | NuGet) - adds ASP.NET Core 10.0 sessions to Atata using WebApplicationFactory.
- Atata.WebDriverSetup (GitHub | NuGet) -
sets up browser drivers, e.g.
chromedriver,geckodriver, etc. Basically, it provides functionality similar to JavaWebDriverManager. - Atata.HtmlValidation (GitHub | NuGet) - adds HTML page validation to Atata using html-validate NPM package.
- Atata.Bootstrap (GitHub | NuGet) - contains a set of Atata components for Bootstrap Framework web UI testing.
- Atata.KendoUI (GitHub | NuGet) - contains a set of Atata components for Kendo UI HTML Framework web UI testing.
Additional packages
- Atata.WebDriverExtras (GitHub | NuGet) - contains extension methods and other extra classes for Selenium WebDriver. Used by Atata.
- Atata.Cli (GitHub | NuGet) - provides an API for CLI.
- Atata.Cli.Npm (GitHub | NuGet) - provides an API for CLI of NPM.
- Atata.Cli.HtmlValidate (GitHub | NuGet) - provides an API for CLI of html-validate NPM package.
Packages selection
- When you create a test project, the core package which you need is Atata.
- You most likely need to add a package that corresponds the testing framework of your choice: Atata.NUnit, Atata.Xunit.v3, Atata.MSTest, or Atata.Reqnroll.NUnit.
- Atata.NLog is recommended to enable logging to files. It is useful for debugging and analyzing test failures, especially on CI pipelines.
- If you want to run and manage ASP.NET Core web application under test locally during test runs, consider adding Atata.AspNetCore.v10 (or .v9, .v8).
- If you want to run and manage Docker containers with web application under test during test runs, consider adding Atata.Testcontainers. For example, you can use container for DB.
- In case of local web UI testing, Atata.WebDriverSetup is recommended to set up browser drivers locally.
- If you want to validate HTML pages, consider adding Atata.HtmlValidation.
Installation
There are 2 options to create a project in Visual Studio for automated testing using Atata Framework: via Atata Templates VS extension; or creating a new project and adding Atata packages via NuGet Package Manager.
Install via Atata Templates
To get started, install Atata Templates Visual Studio extension.
The extension provides the following templates:
- Project templates:
- Atata NUnit Basic Test Project (.NET 8)
- Atata NUnit Basic Test Project (.NET 10)
- Atata NUnit Advanced Test Project (.NET 8)
- Atata NUnit Advanced Test Project (.NET 10)
- Item templates:
- Atata Page Object
- Atata Base Page Object
- Atata Control
- Atata Trigger
- Atata Test Suite
- Atata Global Fixture
Create project
When extension is installed, you can create a project of one of Atata project types. In Visual Studio:
- Go to File/New/Project… or File/Add/New Project… (to add to existing solution).
- Type Atata into search box or choose Atata in “project types” drop-down.
- Choose template, e.g., Atata NUnit Advanced Test Project (.NET 10), and specify project name and location.

Project references
The project is created with NuGet package references:
- Atata
- Atata.NLog (for advanced project)
- Atata.NUnit
- Atata.WebDriverSetup
- Microsoft.NET.Test.Sdk
- NUnit
- NUnit3TestAdapter
Configuration
You don’t need to configure specific browser driver packages, as a project is by default configured to automatically download appropriate driver, by use of Atata.WebDriverSetup package.
In the created project you can specify your testing site base URL and appropriate driver in
GlobalFixture.cs or local.runsettings, depending on a type of project (basic or advanced).
builder.Sessions.AddWebDriver(x => x
.UseStartScopes(AtataContextScopes.Test)
.UseBaseUrl("https://atata.io/")
//...
<BaseUrl>https://atata.io/</BaseUrl>
Just replace "https://atata.io/" string with your URL.
Test fixtures
The created project also contains ready to use SampleTests.cs test suite, which can be either modified or removed:
namespace AtataUITests1;
public sealed class SampleTests : AtataTestSuite
{
[Test]
public void SampleTest() =>
Go.To<OrdinaryPage>()
.PageTitle.Should.Contain("Atata");
}
Further test suite classes are recommended to inherit from AtataTestSuite, or custom TestSuite,
or just choose “Atata NUnit Test Suite” item template in “Add New Item Window”.
Create project targeting other .NET version
- Create a project using one of the project templates: “Atata NUnit Basic Test Project (.NET 8)”, “Atata NUnit Advanced Test Project (.NET 8)”.
- Open project
.csprojfile. - Change the value of
<TargetFramework>tag fromnet8.0to the needed version.<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>NET_VERSION</TargetFramework> <!-- ... --> </PropertyGroup> <!-- ... --> </Project>
Install via NuGet
It is a more custom approach to create Atata testing project. To get started just add Atata NuGet package to the project of Class Library or a test project type in Visual Studio or other IDE.
PM> Install-Package Atata
The Atata package depends on the following packages, which are added transiently:
You might also need to install Atata.WebDriverSetup package
for auto-setup of browser drivers, e.g. chromedriver, geckodriver, etc.
This is a recommended option.
Alternatively, you can rely on built-in WebDriver Selenium Manager.
For .NET non-MTP projects it is required also to add Microsoft.NET.Test.Sdk package to the project that contains tests (no matter NUnit, xUnit, MSTest, etc.).
You are free to select any test engine framework: NUnit, Xunit, MSTest, Reqnroll, etc.
Atata with NUnit
Atata.NUnit library is a bridge between Atata and NUnit framework. Check out Atata.NUnit documentation on Atata.NUnit GitHub repository page.
Installation requires prior installation of Atata package via NuGet.
Add the following packages:
Add a C# class file GlobalFixture.cs for a global Atata configuration.
GlobalFixture.cs
using Atata;
using Atata.NUnit;
namespace SampleApp.UITests;
public sealed class GlobalFixture : AtataGlobalFixture
{
protected override void ConfigureAtataContextBaseConfiguration(AtataContextBuilder builder)
{
builder.Sessions.AddWebDriver(x => x
.UseStartScopes(AtataContextScopes.Test)
.UseChrome(x => x
.WithArguments(
"disable-search-engine-choice-screen",
"window-size=1600,900"))
.UseBaseUrl("https://atata.io/"));
}
protected override void ConfigureGlobalAtataContext(AtataContextBuilder builder)
{
builder.SetUpWebDriversForUse();
}
}
Add a C# class file for a test suite.
using Atata;
using Atata.NUnit;
namespace SampleApp.UITests;
public sealed class SampleTests : AtataTestSuite
{
[Test]
public void SampleTest()
{
// Test method implementation
}
protected override void ConfigureSuiteAtataContext(AtataContextBuilder builder)
{
// Optional test suite-specific configuration
}
protected override void ConfigureTestAtataContext(AtataContextBuilder builder)
{
// Optional test method-specific configuration
}
}
Check out example projects:
Atata with xUnit
Atata.Xunit.v3 library is a bridge between Atata and xUnit v3 framework. Check out Atata.Xunit.v3 documentation on Atata.Xunit.v3 GitHub repository page.
Installation requires prior installation of Atata package via NuGet.
Add the following packages:
- Atata.Xunit.v3
- xunit.v3.core.mtp-off for non-MTP project. For MTP project consider xunit.v3.core.mtp-v2 package, for example. Check out Microsoft Testing Platform (xUnit.net v3).
- xunit.runner.visualstudio
Add a C# class file GlobalFixture.cs for a global Atata configuration.
GlobalFixture.cs
using Atata;
using Atata.Xunit;
namespace SampleApp.UITests;
public sealed class GlobalFixture : AtataGlobalFixture
{
protected override void ConfigureAtataContextBaseConfiguration(AtataContextBuilder builder)
{
builder.Sessions.AddWebDriver(x => x
.UseStartScopes(AtataContextScopes.Test)
.UseChrome(x => x
.WithArguments(
"disable-search-engine-choice-screen",
"window-size=1600,900"))
.UseBaseUrl("https://atata.io/"));
}
protected override void ConfigureGlobalAtataContext(AtataContextBuilder builder)
{
builder.SetUpWebDriversForUse();
}
}
Add a C# class file for a test suite.
using Atata;
using Atata.Xunit;
namespace SampleApp.UITests;
public sealed class SampleTests : AtataTestSuite
{
[Fact]
public void SampleTest()
{
// Test method implementation
}
protected override void ConfigureTestAtataContext(AtataContextBuilder builder)
{
// Optional test method-specific configuration
}
}
Check out example project Atata Samples / Using Xunit.
Atata with MSTest
Atata.MSTest library is a bridge between Atata and MSTest framework. Check out Atata.MSTest documentation on Atata.MSTest GitHub repository page.
Installation requires prior installation of Atata package via NuGet.
Add the following packages:
Add a C# class file GlobalFixture.cs for a global Atata configuration.
GlobalFixture.cs
using Atata;
using Atata.MSTest;
namespace SampleApp.UITests;
[TestClass]
public static class GlobalFixture
{
[AssemblyInitialize]
public static void SetUpAssembly(TestContext testContext)
{
ConfigureAtataContextBaseConfiguration(AtataContext.BaseConfiguration);
MSTestGlobalAtataContextSetup.SetUp(typeof(GlobalFixture), testContext, ConfigureGlobalAtataContext);
}
[AssemblyCleanup]
public static void TearDownAssembly(TestContext testContext)
{
MSTestGlobalAtataContextSetup.TearDown(testContext);
}
private static void ConfigureAtataContextBaseConfiguration(AtataContextBuilder builder)
{
builder.Sessions.AddWebDriver(x => x
.UseStartScopes(AtataContextScopes.Test)
.UseChrome(x => x
.WithArguments(
"disable-search-engine-choice-screen",
"window-size=1600,900"))
.UseBaseUrl("https://atata.io/"));
}
private static void ConfigureGlobalAtataContext(AtataContextBuilder builder)
{
builder.SetUpWebDriversForUse();
}
}
Add a C# class file for a test suite.
using Atata;
using Atata.MSTest;
namespace SampleApp.UITests;
[TestClass]
public sealed class SampleTests : AtataTestSuite
{
[TestMethod]
public void SampleTest()
{
// Test method implementation
}
[ConfiguresSuiteAtataContext]
public static void ConfigureSuiteAtataContext(AtataContextBuilder builder)
{
// Optional test suite-specific configuration
}
protected override void ConfigureTestAtataContext(AtataContextBuilder builder)
{
// Optional test method-specific configuration
}
}
Check out example project Atata Samples / Using MSTest.
Atata with Reqnroll and NUnit
Atata.Reqnroll.NUnit library is a bridge between Atata and Reqnroll+NUnit framework. Check out Atata.Reqnroll.NUnit documentation on Atata.Reqnroll.NUnit GitHub repository page.
Installation requires prior installation of Atata package via NuGet.
Add the following packages:
Add a C# class file GlobalFixture.cs for a global Atata configuration.
GlobalFixture.cs
using Atata;
using Atata.NUnit;
namespace SampleApp.UITests;
public sealed class GlobalFixture : AtataGlobalFixture
{
protected override void ConfigureAtataContextBaseConfiguration(AtataContextBuilder builder)
{
builder.Sessions.AddWebDriver(x => x
.UseStartScopes(AtataContextScopes.Test)
.UseChrome(x => x
.WithArguments(
"disable-search-engine-choice-screen",
"window-size=1600,900"))
.UseBaseUrl("https://atata.io/"));
}
protected override void ConfigureGlobalAtataContext(AtataContextBuilder builder)
{
builder.SetUpWebDriversForUse();
}
}
Add a C# class file GlobalHooks.cs for a Reqnroll global hooks.
using System.Diagnostics.CodeAnalysis;
using Atata;
using Atata.Reqnroll.NUnit;
using Reqnroll;
namespace SampleApp.UITests;
[Binding]
public sealed class GlobalHooks
{
[BeforeFeature]
public static void SetUpFeature(FeatureContext featureContext) =>
ReqnrollAtataContextSetup.SetUpFeature(featureContext, ConfigureFeatureAtataContext);
[AfterFeature]
public static void TearDownFeature(FeatureContext featureContext) =>
ReqnrollAtataContextSetup.TearDownFeature(featureContext);
[BeforeScenario]
[SuppressMessage("Performance", "CA1822:Mark members as static")]
public void SetUpScenario(FeatureContext featureContext, ScenarioContext scenarioContext) =>
ReqnrollAtataContextSetup.SetUpScenario(featureContext, scenarioContext, ConfigureScenarioAtataContext);
[AfterScenario]
[SuppressMessage("Performance", "CA1822:Mark members as static")]
public void TearDownScenario(ScenarioContext scenarioContext) =>
ReqnrollAtataContextSetup.TearDownScenario(scenarioContext);
private static void ConfigureFeatureAtataContext(
AtataContextBuilder builder,
FeatureContext featureContext)
{
// Add extra configuration for feature AtataContext
}
private static void ConfigureScenarioAtataContext(
AtataContextBuilder builder,
FeatureContext featureContext,
ScenarioContext scenarioContext)
{
// Add extra configuration for scenario AtataContext
}
}
Add a C# class file for Reqnroll step definitions.
using Atata;
using Reqnroll;
namespace SampleApp.UITests;
[Binding]
public sealed class SampleSteps : Steps
{
[Given(@"I am on the Sample page")]
public static void GivenIAmOnTheSamplePage() =>
Go.To<OrdinaryPage>();
}
Add a feature file according to Reqnroll documentation.
Check out example project Atata Samples / Using Reqnroll.
Usage
Let’s create a simple web UI test automation project example with a test for Sign In page.
Create project
In Visual Studio create a project using Installation instructions.
Set Atata base URL to "https://demo.atata.io/" either in GlobalFixture.cs or in a configuration file.
Define page object class
SignInPage.cs
namespace AtataDemo.UITests;
using _ = SignInPage;
[Url("signin")]
public sealed class SignInPage : Page<_>
{
public TextInput<_> Email { get; private set; }
public PasswordInput<_> Password { get; private set; }
public Button<_> SignIn { get; private set; }
}
The aspects of the created page object:
[Url("signin")]- sets the relative URL of the page to be navigated to. Good for pages with static URLs.- Default search of
EmailandPasswordcontrols is performed by label. Can be changed/configured. - Default search of
SignInbutton is performed by its text.
Implement test
SignInTests.cs
namespace AtataDemo.UITests;
public sealed class SignInTests : AtataTestSuite
{
[Test]
public void SignIn() =>
Go.To<SignInPage>()
.Email.Type("admin@mail.com")
.Password.Type("abc123")
.SignIn.Click();
}
View log
The above sample SignIn test generates the following log to NUnit output:
00:00:00.000 Vlmf DEBUG Starting test AtataDemo.UITests.SignInTests.SignIn at 2026-05-07 20:09:04.493
00:00:00.000 Vlmf TRACE > Initialize AtataContext { Id=Vlmf }
00:00:00.000 Vlmf TRACE - Set: Artifacts=D:\dev\AtataDemo.UITests\AtataDemo.UITests\bin\Debug\net10.0\artifacts\20260507T200904\SignInTests\SignIn
00:00:00.007 uuoE TRACE - > Initialize WebDriverSession { Id=uuoE }
00:00:00.011 uuoE TRACE - - Set: BaseUrl=https://demo.atata.io/
00:00:00.012 uuoE TRACE - - Set: ElementFindTimeout=5s; ElementFindRetryInterval=0.2s
00:00:00.012 uuoE TRACE - - Set: WaitingTimeout=5s; WaitingRetryInterval=0.2s
00:00:00.012 uuoE TRACE - - Set: VerificationTimeout=5s; VerificationRetryInterval=0.2s
00:00:00.013 uuoE TRACE - - > Initialize Driver
00:00:00.018 uuoE TRACE - - - Created ChromeDriverService { Port=53840, ExecutablePath=D:\dev\_temp\TestProject39\TestProject39\bin\Debug\net10.0\drivers\chrome\147.0.7727.117\chromedriver.exe }
00:00:00.661 uuoE TRACE - - - Created ChromeDriver { Alias=chrome, SessionId=11ba40da88e75b383e17131ca89e9624 }
00:00:00.662 uuoE TRACE - - < Initialize Driver (0.649s)
00:00:00.663 uuoE TRACE - < Initialize WebDriverSession { Id=uuoE } (0.656s)
00:00:00.664 Vlmf TRACE < Initialize AtataContext { Id=Vlmf } (0.664s)
00:00:00.707 uuoE INFO > Go to "Sign In" page by URL https://demo.atata.io/signin
00:00:00.965 uuoE INFO < Go to "Sign In" page by URL https://demo.atata.io/signin (0.257s)
00:00:00.972 uuoE INFO > Type "admin@mail.com" in "Email" text input
00:00:00.974 uuoE TRACE - > Execute behavior TypesTextUsingSendKeysAttribute against "Email" text input
00:00:00.998 uuoE TRACE - - > Find element by XPath "(.//*[@id = //label[normalize-space(.) = 'Email']/@for]/descendant-or-self::input[@type='text' or not(@type)] | .//label[normalize-space(.) = 'Email']/descendant-or-self::input[@type='text' or not(@type)])" in ChromeDriver
00:00:01.221 uuoE TRACE - - < Find element by XPath "(.//*[@id = //label[normalize-space(.) = 'Email']/@for]/descendant-or-self::input[@type='text' or not(@type)] | .//label[normalize-space(.) = 'Email']/descendant-or-self::input[@type='text' or not(@type)])" in ChromeDriver (0.222s) >> Element (id = f.8E06CFE04C6716766F8257A4EE7D9BFD.d.A38F77598C1D7C1A24360A043AF36AE4.e.6)
00:00:01.223 uuoE TRACE - - > Send keys "admin@mail.com" to element (id = f.8E06CFE04C6716766F8257A4EE7D9BFD.d.A38F77598C1D7C1A24360A043AF36AE4.e.6)
00:00:01.302 uuoE TRACE - - < Send keys "admin@mail.com" to element (id = f.8E06CFE04C6716766F8257A4EE7D9BFD.d.A38F77598C1D7C1A24360A043AF36AE4.e.6) (0.079s)
00:00:01.303 uuoE TRACE - < Execute behavior TypesTextUsingSendKeysAttribute against "Email" text input (0.328s)
00:00:01.303 uuoE INFO < Type "admin@mail.com" in "Email" text input (0.331s)
00:00:01.303 uuoE INFO > Type "abc123" in "Password" password input
00:00:01.303 uuoE TRACE - > Execute behavior TypesTextUsingSendKeysAttribute against "Password" password input
00:00:01.304 uuoE TRACE - - > Find element by XPath "(.//*[@id = //label[normalize-space(.) = 'Password']/@for]/descendant-or-self::input[@type='password'] | .//label[normalize-space(.) = 'Password']/descendant-or-self::input[@type='password'])" in ChromeDriver
00:00:01.317 uuoE TRACE - - < Find element by XPath "(.//*[@id = //label[normalize-space(.) = 'Password']/@for]/descendant-or-self::input[@type='password'] | .//label[normalize-space(.) = 'Password']/descendant-or-self::input[@type='password'])" in ChromeDriver (0.013s) >> Element (id = f.8E06CFE04C6716766F8257A4EE7D9BFD.d.A38F77598C1D7C1A24360A043AF36AE4.e.3)
00:00:01.317 uuoE TRACE - - > Send keys "abc123" to element (id = f.8E06CFE04C6716766F8257A4EE7D9BFD.d.A38F77598C1D7C1A24360A043AF36AE4.e.3)
00:00:01.359 uuoE TRACE - - < Send keys "abc123" to element (id = f.8E06CFE04C6716766F8257A4EE7D9BFD.d.A38F77598C1D7C1A24360A043AF36AE4.e.3) (0.041s)
00:00:01.359 uuoE TRACE - < Execute behavior TypesTextUsingSendKeysAttribute against "Password" password input (0.055s)
00:00:01.359 uuoE INFO < Type "abc123" in "Password" password input (0.056s)
00:00:01.359 uuoE INFO > Click "Sign In" button
00:00:01.360 uuoE TRACE - > Execute behavior ClicksUsingClickMethodAttribute against "Sign In" button
00:00:01.361 uuoE TRACE - - > Find element by XPath ".//*[self::input[@type='button' or @type='submit' or @type='reset'] or self::button][normalize-space(.) = 'Sign In' or normalize-space(@value) = 'Sign In']" in ChromeDriver
00:00:01.376 uuoE TRACE - - < Find element by XPath ".//*[self::input[@type='button' or @type='submit' or @type='reset'] or self::button][normalize-space(.) = 'Sign In' or normalize-space(@value) = 'Sign In']" in ChromeDriver (0.014s) >> Element (id = f.8E06CFE04C6716766F8257A4EE7D9BFD.d.A38F77598C1D7C1A24360A043AF36AE4.e.10)
00:00:01.377 uuoE TRACE - - > Click element (id = f.8E06CFE04C6716766F8257A4EE7D9BFD.d.A38F77598C1D7C1A24360A043AF36AE4.e.10)
00:00:01.479 uuoE TRACE - - < Click element (id = f.8E06CFE04C6716766F8257A4EE7D9BFD.d.A38F77598C1D7C1A24360A043AF36AE4.e.10) (0.101s)
00:00:01.479 uuoE TRACE - < Execute behavior ClicksUsingClickMethodAttribute against "Sign In" button (0.118s)
00:00:01.479 uuoE INFO < Click "Sign In" button (0.119s)
00:00:01.481 Vlmf TRACE > Deinitialize AtataContext { Id=Vlmf }
00:00:01.486 uuoE TRACE - > Deinitialize WebDriverSession { Id=uuoE }
00:00:01.592 uuoE TRACE - < Deinitialize WebDriverSession { Id=uuoE } (0.106s)
00:00:01.594 Vlmf TRACE < Deinitialize AtataContext { Id=Vlmf } (0.112s)
00:00:01.596 Vlmf DEBUG Finished test with passed status at 2026-05-07 20:09:06.090
Total time: 1.594s
Initialization: 0.665s | 41.7 %
Test body: 0.816s | 51.2 %
Deinitialization: 0.112s | 7.1 %
Demo
Demo atata-framework/atata-sample-app-tests UI tests application demonstrates different testing approaches and features of Atata Framework. It uses Atata Sample App (repository) as a testing website and NUnit as a test engine.
Features
- Atata configuration and settings set-up.
- Page navigation.
- Controls finding.
- Data input and verification.
- Validation messages verification.
- Usage of triggers.
- Interaction with pop-ups (Bootstrap modal) and alerts.
- Work with tables.
- Logging, screenshots and snapshots.
- Page HTML validation.
Sample test
public sealed class UserTests : TestSuite
{
[Test]
public void Create() =>
Login()
.New()
.ModalTitle.Should.Be("New User")
.General.FirstName.SetRandom(out string firstName)
.General.LastName.SetRandom(out string lastName)
.General.Email.SetRandom(out string email)
.General.Office.SetRandom(out Office office)
.General.Gender.SetRandom(out Gender gender)
.Save()
.GetUserRow(email).View()
.AggregateAssert(x => x
.Header.Should.Be($"{firstName} {lastName}")
.Email.Should.Be(email)
.Office.Should.Be(office)
.Gender.Should.Be(gender)
.Birthday.Should.Not.BeVisible()
.Notes.Should.Not.BeVisible());
//...
}
Configuration
AtataContextBuilder class is responsible for configuring AtataContext instance.
It is a root point of configuration and provides methods to configure various aspects of the context, such as sessions, logging, and other settings.
AtataContextBuilder and other configuration builders provide fluent API methods for configuration.
Basic configuration example
public sealed class GlobalFixture : AtataGlobalFixture
{
protected override void ConfigureAtataContextBaseConfiguration(AtataContextBuilder builder) =>
builder.Sessions.AddWebDriver(x => x
.UseStartScopes(AtataContextScopes.Test)
.UseChrome(x => x
.WithArguments(
"start-maximized",
"disable-search-engine-choice-screen"))
.UseBaseUrl("https://atata.io/"));
protected override void ConfigureGlobalAtataContext(AtataContextBuilder builder) =>
builder.SetUpWebDriversForUse();
}
See full example sources in Atata Samples / NUnit / Basic Test Project.
Advanced configuration example
public sealed class GlobalFixture : AtataGlobalFixture
{
private GlobalConfig? _config;
protected override void OnBeforeGlobalSetup()
{
string testEnvironment = Environment.GetEnvironmentVariable("TestEnvironment") ?? "local";
var configuration = new ConfigurationBuilder()
.AddJsonFile($"config.{testEnvironment}.json")
.AddEnvironmentVariables()
.Build();
_config = configuration.Get<GlobalConfig>();
}
protected override void ConfigureAtataContextBaseConfiguration(AtataContextBuilder builder)
{
builder.LogConsumers.AddNLogFile();
builder.Sessions.AddWebDriver(x => x
.UseStartScopes(AtataContextScopes.Test)
.ConfigureChrome("chrome-headed", x => x
.WithArguments(
"start-maximized",
"disable-search-engine-choice-screen")
.WithArtifactsAsDownloadDirectory())
.ConfigureChrome("chrome-headless", x => x
.WithArguments(
"headless=new",
"window-size=1920,1080",
"disable-search-engine-choice-screen")
.WithArtifactsAsDownloadDirectory())
.UseDriver(_config!.WebDriverAlias)
.UseBaseUrl(_config!.BaseUrl));
}
protected override void ConfigureGlobalAtataContext(AtataContextBuilder builder)
{
builder.UseState(_config);
builder.SetUpWebDriversForUse();
}
}
See full example sources in Atata Samples / NUnit / Advanced Test Project.
Predefined configuration places
If you use Atata together with Atata.NUnit, Atata.Xunit.v3 or similar Atata integration package,
you will not need to create an instance of AtataContextBuilder.
You will rather configure AtataContextBuilder argument in one of the methods of GlobalFixture, like ConfigureAtataContextBaseConfiguration
or in a test suite method like ConfigureSuiteAtataContext.
public sealed class GlobalFixture : AtataGlobalFixture
{
protected override void ConfigureAtataContextBaseConfiguration(AtataContextBuilder builder)
{
// TODO: Configure the builder...
}
}
public sealed class SomeTests : AtataTestSuite
{
protected override void ConfigureSuiteAtataContext(AtataContextBuilder builder)
{
// TODO: Configure the builder...
}
}
Look for all the available virtual methods with AtataContextBuilder parameter in the corresponding package repository page, e.g. Atata.NUnit.
Custom builder creation
You can also configure AtataContext in a custom way, without using Atata integration packages.
There are several static AtataContext methods available to create AtataContextBuilder instance:
public static AtataContextBuilder CreateBuilder(AtataContextScope scope);
public static AtataContextBuilder CreateDefaultBuilder(AtataContextScope scope);
public static AtataContextBuilder CreateNonScopedBuilder();
public static AtataContextBuilder CreateDefaultNonScopedBuilder();
AtataContext.CreateBuilder(AtataContextScope.Test)
// Configure the builder...
.Build();
“Default” methods create a builder with default/blank configuration,
while non-“default” methods create a builder with configuration copied from the AtataContext.BaseConfiguration.
AtataContextScope is a enumeration containing the following values:
Test, TestSuite, TestSuiteGroup, Namespace, and Global.
AtataContextBuilder
AtataContextBuilder methods
Sessions { get; }
Gets the builder of sessions, which provides the functionality to add/configure/remove sessions and session providers.
Attributes { get; }
Gets the builder of context attributes, which provides the functionality to add extra attributes to different metadata levels: global, assembly, component and property.
EventSubscriptions { get; }
Gets the builder of event subscriptions, which provides the methods to subscribe to Atata and custom events.
LogConsumers { get; }
Gets the builder of log consumers, which provides the methods to add log consumers.
Use(Action<AtataContextBuilder> configure)
Configures this builder by action delegate.
UseParentContext(AtataContext? parentContext)
Sets the parent context.
UseVariable(string key, object? value)
Sets the variable.
UseVariables(IEnumerable<KeyValuePair<string, object?>> variables)
Sets the variables.
UseState <TValue>(TValue value)
Sets the state object.
UseState(string key, object? value)
Sets the state object.
UseState(IEnumerable<KeyValuePair<string, object?>> objects)
Sets the state objects.
AddSecretStringToMaskInLog(string value, string mask = "{*****}")
Adds the secret string to mask in log.
UseTestName(string? testName)
Sets the name of the test.
UseTestName(Func <string?> testNameFactory)
Sets the factory method of the test name.
UseTestSuiteName(string? testSuiteName)
Sets the name of the test suite (class).
UseTestSuiteName(Func <string?> testSuiteNameFactory)
Sets the factory method of the test suite (class) name.
UseTestSuiteType(Type? testSuiteType)
Sets the type of the test suite class.
UseTestSuiteType(Func <Type?> testSuiteTypeFactory)
Sets the factory method of the test suite class type.
UseTestSuiteGroupName(string? testSuiteGroupName)
Sets the name of the test suite group (collection fixture).
UseTestSuiteGroupName(Func <string?> testSuiteGroupNameFactory)
Sets the factory method of the test suite group (collection fixture) name.
UseTestTraits(IReadOnlyList<TestTrait>? testTraits)
Sets the test traits.
UseTestTraits(Func<IReadOnlyList<TestTrait>?> testTraitsFactory)
Sets the factory method of the test traits.
UseBaseRetryTimeout(TimeSpan timeout)
Sets the base retry timeout. The default value is 5 seconds.
UseBaseRetryInterval(TimeSpan interval)
Sets the base retry interval. The default value is 200 milliseconds.
UseWaitingTimeout(TimeSpan timeout)
Sets the waiting timeout.
The default value is taken from BaseRetryTimeout, which is equal to 5 seconds by default.
UseWaitingRetryInterval(TimeSpan interval)
Sets the waiting retry interval.
The default value is taken from BaseRetryInterval, which is equal to 200 milliseconds by default.
UseVerificationTimeout(TimeSpan timeout)
Sets the verification timeout.
The default value is taken from BaseRetryTimeout, which is equal to 5 seconds by default.
UseVerificationRetryInterval(TimeSpan interval)
Sets the verification retry interval.
The default value is taken from BaseRetryInterval, which is equal to 200 milliseconds by default.
UseDefaultCancellationToken(CancellationToken cancellationToken)
Sets the default cancellation token. The default value is CancellationToken.None.
UseCulture(CultureInfo culture)
Sets the culture. The default value is CultureInfo.CurrentCulture.
UseCulture(string cultureName)
Sets the culture by the name. The default value is CultureInfo.CurrentCulture.
UseAssertionExceptionFactory(IAssertionExceptionFactory factory)
Sets the assertion exception factory.
The default value is an instance of AtataAssertionExceptionFactory.
UseAggregateAssertionExceptionFactory(IAggregateAssertionExceptionFactory factory)
Sets the aggregate assertion strategy.
UseAggregateAssertionStrategy(IAggregateAssertionStrategy strategy)
Sets the aggregate assertion strategy.
The default value is an instance of AtataAggregateAssertionStrategy.
UseWarningReportStrategy(IWarningReportStrategy strategy)
Sets the strategy for warning assertion reporting.
The default value is an instance of AtataWarningReportStrategy.
UseAssertionFailureReportStrategy(IAssertionFailureReportStrategy strategy)
Sets the strategy for assertion failure reporting.
The default value is an instance of AtataAssertionFailureReportStrategy.
UseCleanUpArtifactsCondition(TestResultStatusCondition condition)
Sets the condition under which Artifacts directory should be deleted depending on a test result status.
The default value is TestResultStatusCondition.None.
Clear()
Creates a new clean AtataContextBuilder instance with the same scope arguments.
If this instance is BaseConfiguration, sets the new cleared instance into AtataContext.BaseConfiguration.
Clone()
Creates a copy of the current builder.
CloneFor(AtataContextScope scope)
Creates a copy of the current builder for the specified scope.
Build(CancellationToken cancellationToken = default)
BuildAsync(CancellationToken cancellationToken = default)
Builds the AtataContext instance and sets it to AtataContext.Current property.
AtataContextBuilder extension methods for WebDriver setup
In order to use the following methods, ensure that Atata.WebDriverSetup package is installed.
SetUpWebDrivers(params string[] browserNames)
Adds SetUpWebDriversEventHandler instance to the AtataContextBuilder.EventSubscriptions collection.
The SetUpWebDriversEventHandler sets up drivers with auto version detection for the specified browsers.
SetUpWebDriversForUse()
Adds SetUpWebDriversForUseEventHandler instance to the AtataContextBuilder.EventSubscriptions collection.
The SetUpWebDriversForUseEventHandler sets up drivers with automatic version detection for the local browsers,
which are specified in the preconfigured WebDriverSessionBuilder instances as drivers to use.
SetUpWebDriversConfigured()
Adds SetUpWebDriversConfiguredEventHandler instance to the AtataContextBuilder.EventSubscriptions collection.
The SetUpWebDriversConfiguredEventHandler sets up drivers with automatic version detection for the local browsers,
which are specified in the preconfigured WebDriverSessionBuilder instances as configured drivers.
Global properties
The static AtataContext.GlobalProperties property
contains global properties that should be configured as early as possible,
and not changed later,
because these properties should have the same values for all the contexts within a single execution.
Typically you configure global properties in overridden ConfigureAtataContextGlobalProperties method of custom GlobalFixture class.
public sealed class GlobalFixture : AtataGlobalFixture
{
protected override void ConfigureAtataContextGlobalProperties(AtataContextGlobalProperties globalProperties)
{
globalProperties.UseDefaultArtifactsRootPathTemplateExcludingRunStartOnCI();
}
}
Alternatively, you can configure global properties in global setup method before any creation of AtataContext.
AtataContext.GlobalProperties.UseDefaultArtifactsRootPathTemplateExcludingRunStartOnCI();
The list of AtataContextGlobalProperties configuration methods:
UseArtifactsRootPathTemplate(string directoryPathTemplate)
Sets the path template of the Artifacts Root directory.
The default value is "{basedir}/artifacts/{run-start:yyyyMMddTHHmmss}".
The list of supported variables:
{basedir}{run-start}{run-start-utc}
UseDefaultArtifactsRootPathTemplateIncludingRunStart(string include)
Sets the default Artifacts Root path template with optionally
including "{run-start:yyyyMMddTHHmmss}" folder in the path.
UseDefaultArtifactsRootPathTemplateExcludingRunStartOnCI()
Sets the default Artifacts Root path template
excluding "{run-start:yyyyMMddTHHmmss}" folder in the path on CI environment.
UseArtifactsPathFactory(IArtifactsPathFactory artifactsPathFactory)
Sets the artifacts path factory.
UseRootNamespaceOf(string? rootNamespace)
Sets the root namespace.
UseRootNamespaceOf <T>()
Sets the root namespace with the namespace of the specified T type.
UseRootNamespaceOf(Type type)
Sets the root namespace with the namespace of the specified type.
UseTimeZone(TimeZoneInfo timeZone)
Sets the time zone.
UseTimeZone(string timeZoneId)
Sets the time zone by identifier, which corresponds to the TimeZoneInfo.Id property.
UseUtcTimeZone()
Sets the UTC time zone.
UseModeOfCurrent(AtataContextModeOfCurrent mode)
Sets the mode of AtataContext.Current property.
The default value is AtataContextModeOfCurrent.AsyncLocal.
UseAssemblyNamePatternToFindTypes(string pattern)
Sets the assembly name regex pattern that is used to filter assemblies to find types in them,
such as events, event handlers, attributes, components, etc.
The default value is
@"^(?!System($|\..+)|mscorlib$|netstandard$|Microsoft\..+|testhost$|(?i:testcentric\..+)|(?i:nunit)|(?i:xunit))",
which excludes system and some well known assemblies.
UseIdGenerator(IAtataIdGenerator idGenerator)
Sets the identifier generator.
The default value is an instance of Alphanumeric4AtataIdGenerator.
Sessions
Sessions can be registered or configured through the methods of Sessions property of AtataContextBuilder during a context configuration.
builder.Sessions.AddWebDriver(x => x
.UseStartScopes(AtataContextScopes.Test)
.UseBaseUrl(baseUrl));
builder.Sessions.Borrow<WebDriverSession>("primary");
builder.Sessions.TakeFromPool<WebDriverSession>(x => x.UseSharedMode(true));
Also it is possible to build or request a session directly using methods of Sessions property of AtataContext instance.
AtataSessionsBuilder methods
Add <TSessionBuilder>(Action<TSessionBuilder>? configure = null)
where TSessionBuilder : IAtataSessionBuilder, new()
Creates a new instance of the builder of the specified TSessionBuilder type,
calls the configure delegate,
adds it to the session providers list.
Add(IAtataSessionProvider sessionProvider)
Adds the specified session provider.
Configure <TSessionBuilder>(Action<TSessionBuilder> configure, ConfigurationMode mode = default)
where TSessionBuilder : IAtataSessionBuilder
Configures existing nameless TSessionBuilder session builder.
The mode (ConfigurationMode.ConfigureOrThrow by default)
parameter specifies the behavior of the fallback logic when the session builder is not found:
ConfigurationMode.ConfigureOrThrow- configures the builder or throws theAtataSessionBuilderNotFoundExceptionif it is not found.ConfigurationMode.ConfigureIfExists- configures the builder only if it exists; otherwise, no action is taken.ConfigurationMode.ConfigureOrAdd- configures the builder if it exists, or adds a new builder if it does not exist.
Configure <TSessionBuilder>(string? name, Action<TSessionBuilder> configure, ConfigurationMode mode = default)
where TSessionBuilder : IAtataSessionBuilder
Configures existing TSessionBuilder session builder that has the specified name.
The mode (ConfigurationMode.ConfigureOrThrow by default)
parameter specifies the behavior of the fallback logic when the session builder is not found:
ConfigurationMode.ConfigureOrThrow- configures the builder or throws theAtataSessionBuilderNotFoundExceptionif it is not found.ConfigurationMode.ConfigureIfExists- configures the builder only if it exists; otherwise, no action is taken.ConfigurationMode.ConfigureOrAdd- configures the builder if it exists, or adds a new builder if it does not exist.
Configure(Type? sessionType, string? name, Action<TSessionBuilder> configure, ConfigurationMode mode = default)
Configures existing TSessionBuilder session builder that has the specified sessionType and name.
The mode (ConfigurationMode.ConfigureOrThrow by default)
parameter specifies the behavior of the fallback logic when the session builder is not found:
ConfigurationMode.ConfigureOrThrow- configures the builder or throws theAtataSessionBuilderNotFoundExceptionif it is not found.ConfigurationMode.ConfigureIfExists- configures the builder only if it exists; otherwise, no action is taken.ConfigurationMode.ConfigureOrAdd- configures the builder if it exists, or adds a new builder if it does not exist.
Borrow <TSession>(Action<AtataSessionBorrowRequestBuilder>? configure = null)
where TSession : AtataSession
Creates a request to borrow a session of the specified TSession type,
calls the configure delegate,
adds it to the session providers list.
Borrow <TSession>(string? name, Action<AtataSessionBorrowRequestBuilder>? configure = null)
where TSession : AtataSession
Creates a request to borrow a session of the specified TSession type with the specified name,
calls the configure delegate,
adds it to the session providers list.
Borrow(Type sessionType, Action<AtataSessionBorrowRequestBuilder>? configure = null)
Creates a request to borrow a session of the specified sessionType,
calls the configure delegate,
adds it to the session providers list.
Borrow(string name, Action<AtataSessionBorrowRequestBuilder>? configure = null)
Creates a request to borrow a session of the specified name,
calls the configure delegate,
adds it to the session providers list.
Borrow(Type? sessionType, string? name, Action<AtataSessionBorrowRequestBuilder>? configure = null)
Creates a request to borrow a session of the specified sessionType and name,
calls the configure delegate,
adds it to the session providers list.
TakeFromPool <TSession>(Action<AtataSessionPoolRequestBuilder>? configure = null)
where TSession : AtataSession
Creates a request to take a session from the pool of the specified TSession type,
calls the configure delegate,
adds it to the session providers list.
TakeFromPool <TSession>(string? name, Action<AtataSessionPoolRequestBuilder>? configure = null)
where TSession : AtataSession
Creates a request to take a session from the pool of the specified TSession type with the specified name,
calls the configure delegate,
adds it to the session providers list.
TakeFromPool(Type sessionType, Action<AtataSessionPoolRequestBuilder>? configure = null)
Creates a request to take a session from the pool of the specified sessionType,
calls the configure delegate,
adds it to the session providers list.
TakeFromPool(string name, Action<AtataSessionPoolRequestBuilder>? configure = null)
Creates a request to take a session from the pool of the specified name,
calls the configure delegate,
adds it to the session providers list.
TakeFromPool(Type? sessionType, string? name, Action<AtataSessionPoolRequestBuilder>? configure = null)
Creates a request to take a session from the pool of the specified sessionType and name,
calls the configure delegate,
adds it to the session providers list.
Remove(IAtataSessionProvider sessionProvider)
Removes the specified session provider.
RemoveAll <TSessionBuilder>()
where TSessionBuilder : IAtataSessionBuilder
Removes all session providers of the specified TSessionProvider type.
RemoveAll <TSessionBuilder>(string? name)
where TSessionBuilder : IAtataSessionBuilder
Removes all session providers of the specified TSessionProvider type and name.
RemoveAll(Type? sessionType, string? name)
Removes all session providers by the specified sessionType and name.
At least one of the parameters should be not null.
RemoveAllBySessionType <TSession>()
Removes all session providers of the specified TSession session type regardless of name.
RemoveAllBySessionType <TSession>(string? name)
Removes all session providers of the specified TSession session type and name.
RemoveAllBySessionType(Type sessionType)
Removes all session providers of the specified sessionType session type regardless of name.
RemoveAllBySessionType(Type sessionType, string? name)
Removes all session providers of the specified sessionType session type and name.
RemoveAllBySessionName(string name)
Removes all session providers with the specified name.
DisableAll <TSessionBuilder>()
where TSessionBuilder : IAtataSessionBuilder
Disables all session providers of the specified TSessionProvider type.
Sets their IAtataSessionProvider.StartScopes property to AtataContextScopes.None,
so that the sessions will not automatically start for any scope.
DisableAll <TSessionBuilder>(string? name)
where TSessionBuilder : IAtataSessionBuilder
Disables all session providers of the specified TSessionProvider type and name.
Sets their IAtataSessionProvider.StartScopes property to AtataContextScopes.None,
so that the sessions will not automatically start for any scope.
DisableAll(Type? sessionType, string? name)
Disables all session providers by the specified sessionType and name.
Sets their IAtataSessionProvider.StartScopes property to AtataContextScopes.None,
so that the sessions will not automatically start for any scope.
At least one of the parameters should be not null.
DisableAllBySessionType <TSession>()
Disables all session providers of the specified TSession session type regardless of name.
Sets their IAtataSessionProvider.StartScopes property to AtataContextScopes.None,
so that the sessions will not automatically start for any scope.
DisableAllBySessionType <TSession>(string? name)
Disables all session providers of the specified TSession session type and name.
Sets their IAtataSessionProvider.StartScopes property to AtataContextScopes.None,
so that the sessions will not automatically start for any scope.
DisableAllBySessionType(Type sessionType)
Disables all session providers of the specified sessionType session type regardless of name.
Sets their IAtataSessionProvider.StartScopes property to AtataContextScopes.None,
so that the sessions will not automatically start for any scope.
DisableAllBySessionType(Type sessionType, string? name)
Disables all session providers of the specified sessionType session type and name.
Sets their IAtataSessionProvider.StartScopes property to AtataContextScopes.None,
so that the sessions will not automatically start for any scope.
DisableAllBySessionName(string name)
Disables all session providers with the specified name.
Sets their IAtataSessionProvider.StartScopes property to AtataContextScopes.None,
so that the sessions will not automatically start for any scope.
Clear()
Clears all session providers.
AtataSessionsBuilder extension methods for WebDriver sessions
AddWebDriver(Action<WebDriverSessionBuilder>? configure = null)
Adds a new instance of WebDriverSessionBuilder builder.
ConfigureWebDriver(Action<WebDriverSessionBuilder> configure, ConfigurationMode mode = default)
Configures existing nameless WebDriverSessionBuilder session builder.
ConfigureWebDriver(string? name, Action<WebDriverSessionBuilder> configure, ConfigurationMode mode = default)
Configures existing WebDriverSessionBuilder session builder that has the specified name.
Session
Session configuration can be done using a couple of classes (listed as inheritance hierarchy):
AtataSessionBuilderBase<TBuilder>- a base builder for creating and configuring session providers.AtataSessionBuilder<TSession, TBuilder>- a builder for creating and configuring anAtataSession.AtataSessionRequestBuilder<TBuilder>- a builder of a session request.AtataSessionBorrowRequestBuilder- a builder of a session borrow request.AtataSessionPoolRequestBuilder- a builder of a session taking from pool request.
AtataSessionBuilderBase<TBuilder> methods
Use(Action<TBuilder> configure)
Configures this builder by action delegate.
UseName(string? name)
Sets the Name value for a session.
UseStartScopes(AtataContextScopes startScopes)
Sets the StartScopes (the scopes for which an AtataSession should automatically start) value for a session.
UseStart(bool start = true)
Sets the StartScopes value for a session
with either AtataContextScopes.All or AtataContextScopes.None,
depending on the start parameter.
UseStartCondition(Func<AtataContext, bool> predicate)
UseStartCondition(Func<AtataContext, Task<bool>> predicate)
UseStartCondition(Func<AtataContext, ValueTask<bool>> predicate)
Adds a start condition predicate that determines whether the session should be started for the provided AtataContext.
UseStartWhenPortIsAvailable(int port)
Adds a start condition that verifies whether the specified TCP port is available.
The condition succeeds when the port is available.
AtataSessionBuilder<TSession, TBuilder> methods
AddDependentConfiguration <TOtherSession>(Action<TOtherSession> configure)
where TOtherSession : AtataSession
AddDependentConfiguration <TOtherSession>(Action<TBuilder, TOtherSession> configure)
where TOtherSession : AtataSession
AddDependentConfiguration <TOtherSession>(string? sessionName, Action<TOtherSession> configure)
where TOtherSession : AtataSession
AddDependentConfiguration <TOtherSession>(string? sessionName, Action<TBuilder, TOtherSession> configure)
where TOtherSession : AtataSession
Adds the specified dynamic configuration action that depends on a specific session.
This action will be executed when the session is building.
If the dependent session is not found recursively in contexts during session building, an AtataSessionNotFoundException will be thrown.
AddDynamicConfiguration(Action<TBuilder> configure)
AddDynamicConfiguration(Action<TBuilder, AtataContext> configure)
Adds the specified dynamic configuration action. This action will be executed when the session is building.
UseStartCount(int count)
Sets the StartCount value, the count of sessions to build on startup.
The default value is 1.
Applies when Mode is set to
AtataSessionMode.Own or AtataSessionMode.Shared.
UseStartMultipleInParallel(bool enable)
Sets the StartMultipleInParallel value,
a value indicating whether to build multiple sessions in parallel on startup
when StartCount is more than 1;
or in case of pool mode, when PoolInitialCapacity is more than 1.
The default value is true.
UseAsOwn()
Sets the session mode to AtataSessionMode.Own (the default mode).
UseAsShared()
Sets the session mode to AtataSessionMode.Shared.
UseAsPool(Action<AtataSessionPoolBuilder>? configure = null)
Sets the session mode to AtataSessionMode.Pool and optionally configures the session pool.
UseVariable(string key, object value)
Sets the variable.
UseVariables(IEnumerable<KeyValuePair<string, object>> variables)
Sets the variables.
UseState <TValue>(TValue value)
UseState(string key, object value)
Sets the state object.
UseState(IEnumerable<KeyValuePair<string, object>> variables)
Sets the state objects.
UseBaseRetryTimeout(TimeSpan? timeout)
Sets the base retry timeout for session.
The default value is null.
When null, the value for session will be taken from AtataContext.BaseRetryTimeout,
which is equal to 5 seconds by default.
UseBaseRetryInterval(TimeSpan? interval)
Sets the base retry interval for session.
The default value is null.
When null, the value for session will be taken from AtataContext.BaseRetryInterval,
which is equal to 200 milliseconds by default.
UseWaitingTimeout(TimeSpan? timeout)
Sets the waiting timeout for session.
The default value is null.
When null, the value for session will be taken from
BaseRetryTimeout or AtataContext.WaitingTimeout,
which are equal to 5 seconds by default.
UseWaitingRetryInterval(TimeSpan? interval)
Sets the waiting retry interval for session.
The default value is null.
When null, the value for session will be taken from
BaseRetryTimeout or AtataContext.WaitingRetryInterval,
which are equal to 200 milliseconds by default.
UseVerificationTimeout(TimeSpan? timeout)
Sets the verification timeout for session.
The default value is null.
When null, the value for session will be taken from
BaseRetryTimeout or AtataContext.VerificationTimeout,
which are equal to 5 seconds by default.
UseVerificationRetryInterval(TimeSpan? interval)
Sets the verification retry interval for session.
The default value is null.
When null, the value for session will be taken from
BaseRetryTimeout or AtataContext.VerificationRetryInterval,
which are equal to 200 milliseconds by default.
UseSessionWaitingTimeout(TimeSpan timeout)
Sets the session waiting timeout,
which is used in session borrowing and getting from pool.
The default value is 5 minutes.
UseSessionWaitingRetryInterval(TimeSpan interval)
Sets the session waiting retry interval,
which is used in session borrowing and getting from pool.
The default value is 200 milliseconds.
BuildAsync(CancellationToken cancellationToken = default)
Builds the session within a target AtataContext,
AtataContext.Current, or creates a temporary default non-scoped context.
AtataSessionRequestBuilder<TBuilder> methods
UseStartCount(int count)
Sets the StartCount value, the count of sessions to request on startup.
The default value is 1.
UseStartMultipleInParallel(bool enable)
Sets the StartMultipleInParallel value, the count of sessions to request on startup.
The default value is 1.
AtataSessionPoolRequestBuilder methods
UseSharedMode(bool enable)
Sets a value indicating whether to use a shared session mode.
Shared session can be borrowed by child contexts.
The default value is false.
WebDriver session
builder.Sessions.AddWebDriver(x => x
.UseStartScopes(AtataContextScopes.Test)
.UseChrome(x => x
.WithArguments(
"disable-search-engine-choice-screen",
"window-size=1200,800",
"headless=new"))
.UseBaseUrl(_config!.BaseUrl));
The main class for WebDriverSession configuration is WebDriverSessionBuilder,
which inherits from WebSessionBuilder<TSession, TBuilder>,
which in turn inherits from AtataSessionBuilder<TSession, TBuilder>.
WebSessionBuilder<TSession, TBuilder> methods
UseBaseUrl(string? baseUrl)
UseBaseUrl(Uri? baseUrl)
Sets the base URL.
UseElementFindTimeout(TimeSpan? timeout)
Sets the element find timeout for session.
The default value is null.
When null, the value for session will be taken from
BaseRetryTimeout or AtataContext.BaseRetryTimeout,
which are equal to 5 seconds by default.
UseElementFindRetryInterval(TimeSpan? interval)
Sets the element find retry interval for session.
The default value is null.
When null, the value for session will be taken from
BaseRetryInterval or AtataContext.BaseRetryInterval,
which are equal to 200 milliseconds by default.
UseDomTestIdAttributeName(string name)
Sets the name of the DOM test identifier attribute.
The default value is "data-testid".
UseDomTestIdAttributeDefaultCase(TermCase defaultCase)
Sets the default case of the DOM test identifier attribute.
The default value is TermCase.Kebab.
UseWaitForDomImmutableStateTime(TimeSpan value)
Sets the waiting time span that is used as a time of immutable/stable DOM state.
The default value is 100 milliseconds.
WebDriverSessionBuilder methods
UseChrome(Action<ChromeDriverBuilder>? configure = null)
Creates and configures a new builder for ChromeDriver
with default WebDriverAliases.Chrome alias.
Sets this builder as a one to use for a driver creation.
UseFirefox(Action<FirefoxDriverBuilder>? configure = null)
Creates and configures a new builder for FirefoxDriver
with default WebDriverAliases.Firefox alias.
Sets this builder as a one to use for a driver creation.
UseInternetExplorer(Action<InternetExplorerDriverBuilder>? configure = null)
Creates and configures a new builder for InternetExplorerDriver
with default WebDriverAliases.InternetExplorer alias.
Sets this builder as a one to use for a driver creation.
UseEdge(Action<EdgeDriverBuilder>? configure = null)
Creates and configures a new builder for EdgeDriver
with default WebDriverAliases.Edge alias.
Sets this builder as a one to use for a driver creation.
UseSafari(Action<SafariDriverBuilder>? configure = null)
Creates and configures a new builder for SafariDriver
with default WebDriverAliases.Safari alias.
Sets this builder as a one to use for a driver creation.
UseRemoteDriver(Action<RemoteDriverBuilder>? configure = null)
Creates and configures a new builder for RemoteWebDriver
with default WebDriverAliases.Remote alias.
Sets this builder as a one to use for a driver creation.
ConfigureChrome(Action<ChromeDriverBuilder>? configure = null)
Configures an existing or creates a new builder for ChromeDriver with default WebDriverAliases.Chrome alias.
ConfigureChrome(string alias, Action<ChromeDriverBuilder>? configure = null)
Configures an existing or creates a new builder for ChromeDriver with the specified alias.
ConfigureFirefox(Action<FirefoxDriverBuilder>? configure = null)
Configures an existing or creates a new builder for FirefoxDriver with default WebDriverAliases.Firefox alias.
ConfigureFirefox(string alias, Action<FirefoxDriverBuilder>? configure = null)
Configures an existing or creates a new builder for FirefoxDriver with the specified alias.
ConfigureInternetExplorer(Action<InternetExplorerDriverBuilder>? configure = null)
Configures an existing or creates a new builder for InternetExplorerDriver with default WebDriverAliases.InternetExplorer alias.
ConfigureInternetExplorer(string alias, Action<InternetExplorerDriverBuilder>? configure = null)
Configures an existing or creates a new builder for InternetExplorerDriver with the specified alias.
ConfigureEdge(Action<EdgeDriverBuilder>? configure = null)
Configures an existing or creates a new builder for EdgeDriver with default WebDriverAliases.Edge alias.
ConfigureEdge(string alias, Action<EdgeDriverBuilder>? configure = null)
Configures an existing or creates a new builder for EdgeDriver with the specified alias.
ConfigureSafari(Action<SafariDriverBuilder>? configure = null)
Configures an existing or creates a new builder for SafariDriver with default WebDriverAliases.Safari alias.
ConfigureSafari(string alias, Action<SafariDriverBuilder>? configure = null)
Configures an existing or creates a new builder for SafariDriver with the specified alias.
ConfigureRemoteDriver(Action<RemoteWebDriverBuilder>? configure = null)
Configures an existing or creates a new builder for RemoteWebDriver with default WebDriverAliases.Remote alias.
ConfigureRemoteDriver(string alias, Action<RemoteWebDriverBuilder>? configure = null)
Configures an existing or creates a new builder for RemoteWebDriver with the specified alias.
ConfigureDriver <TDriverBuilder>(Func<TDriverBuilder> driverBuilderCreator, Action<TDriverBuilder>? configure = null)
where TDriverBuilder : WebDriverBuilder<TDriverBuilder>
Configures an existing or creates a new builder for TDriverBuilder by the specified alias.
UseDriver <TDriverBuilder>(Action<TDriverBuilder>? configure = null)
where TDriverBuilder : WebDriverBuilder<TDriverBuilder>, new()
UseDriver <TDriverBuilder>(TDriverBuilder driverBuilder, Action<TDriverBuilder>? configure = null)
where TDriverBuilder : WebDriverBuilder<TDriverBuilder>
Use the driver builder.
UseDriver(string alias)
Sets the driver to use by the specified alias.
UseDriver(IWebDriver driver, Action<CustomWebDriverBuilder>? configure = null)
Use the specified driver instance.
UseDriver(Func<IWebDriver> driverFactory, Action<CustomWebDriverBuilder>? configure = null)
Use the custom driver factory method.
UseDisposeDriver(bool disposeDriver)
Sets a value indicating whether to dispose the WebDriverSession.Driver
when AtataSession.DisposeAsync method is invoked.
The default value is true.
UseDefaultControlVisibility(Visibility visibility)
Sets the default control visibility.
The default value is Visibility.Any.
WebDriver
It is possible to configure the driver using the following methods of driver builders.
The amount of methods vary dependently of the driver builder type,
for example ChromeDriverBuilder and EdgeDriverBuilder support the most amount.
WithArguments(params string[] arguments)
WithArguments(IEnumerable<string> arguments)
Adds arguments to be appended to the browser executable command line.
WithAlias(string alias)
Specifies the driver alias.
WithDownloadDirectory(string directoryPath)
Adds the download.default_directory user profile preference to options
with the value specified by directoryPath.
WithDownloadDirectory(Func<string> directoryPathBuilder)
Adds the download.default_directory user profile preference to options
with the value specified by directoryPathBuilder.
WithArtifactsAsDownloadDirectory()
Adds the download.default_directory user profile preference to options
with the value of Artifacts directory path.
WithOptions{DriverOptions} options)
Specifies the driver options.
WithOptions(Func<{DriverOptions}> optionsCreator)
Specifies the driver options factory method.
WithOptions(Action<{DriverOptions}> optionsInitializer)
Specifies the driver options initialization method.
WithOptions(Dictionary <string, object> optionsPropertiesMap)
Specifies the properties map for the driver options.
AddAdditionalOption(string optionName, object optionValue)
Adds the additional option to the driver options.
AddAdditionalBrowserOption(string optionName, object optionValue)
Adds the additional browser option to the driver options.
WithDriverService(Func<{DriverService}> driverServiceCreator)
Specifies the driver service factory method.
WithDriverService(Action <{DriverService}> serviceInitializer)
Specifies the driver service initialization method.
WithDriverService(Dictionary <string, object> servicePropertiesMap)
Specifies the properties map for the driver service.
WithDriverPath(string driverPath)
Specifies the directory containing the driver executable file.
WithLocalDriverPath()
Specifies that local/current directory should be used as the directory containing the driver executable file.
Uses AppDomain.CurrentDomain.BaseDirectory as driver folder path.
This configuration option makes sense for .NET Core 2.0+ project that uses driver as a project package (hosted in the same build directory).
WithDriverExecutableFileName(string driverExecutableFileName)
Specifies the name of the driver executable file.
WithCommandTimeout(TimeSpan commandTimeout)
Specifies the command timeout (the maximum amount of time to wait for each command). The default timeout is 60 seconds.
WithHostName(string hostName)
Specifies the host name of the service.
The default value is localhost.
Can be set to "127.0.0.1", for example when you experience localhost resolve issues.
WithCreateRetries(int createRetries)
Specifies the count of possible driver creation retries in case exceptions occur during creation.
The default value is 2.
Set 0 to omit retries.
WithInitialHealthCheck(bool enable = true)
Enables or disables an initial health check.
By default it is disabled.
When enabled, the default health check function requests IWebDriver.Url.
The health check function can be changed by using WithInitialHealthCheckFunction(Func<IWebDriver, bool>) method.
WithInitialHealthCheckFunction(Func<IWebDriver, bool> function)
Sets the initial health check function.
The default function requests IWebDriver.Url.
WithPortsToIgnore(params int[] portsToIgnore)
WithPortsToIgnore(IEnumerable<int> portsToIgnore)
Specifies the ports to ignore.
Logging
Atata generates many log entries during execution and send them to log consumers.
The log consumers can be registered through the methods of LogConsumers property of AtataContextBuilder.
builder.LogConsumers.AddNLogFile();
builder.LogConsumers.AddNLogFile(x => x
.WithSectionEnd(LogSectionEndOption.Exclude)
.WithMinLevel(LogLevel.Info));
The list of log configuration methods of LogConsumersBuilder:
Add <TLogConsumer>(Action<LogConsumerBuilder<TLogConsumer>>? configure = null)
where TLogConsumer : ILogConsumer, new()
Add <TLogConsumer>(TLogConsumer consumer, Action<LogConsumerBuilder<TLogConsumer>>? configure = null)
where TLogConsumer : ILogConsumer
Adds the log consumer.
Add(string typeNameOrAlias, Action<LogConsumerBuilder<TLogConsumer>>? configure = null)
Adds the log consumer by its type name or alias.
Predefined aliases are defined in LogConsumerAliases static class.
Configure <TLogConsumer>(Action<LogConsumerBuilder<TLogConsumer>> configure, ConfigurationMode mode = default)
where TLogConsumer : ILogConsumer
Configures a log consumer builder for existing TLogConsumer log consumer.
The mode (ConfigurationMode.ConfigureOrThrow by default)
parameter specifies the behavior of the fallback logic when the log consumer builder is not found:
ConfigurationMode.ConfigureOrThrow- configures the builder or throws theLogConsumerNotFoundExceptionif it is not found.ConfigurationMode.ConfigureIfExists- configures the builder only if it exists; otherwise, no action is taken.ConfigurationMode.ConfigureOrAdd- configures the builder if it exists, or adds a new builder if it does not exist.
AddTrace(Action<LogConsumerBuilder<TraceLogConsumer>>? configure = null)
Adds the TraceLogConsumer instance that uses System.Diagnostics.Trace class for logging.
AddDebug(Action<LogConsumerBuilder<DebugLogConsumer>>? configure = null)
Adds the DebugLogConsumer instance that uses System.Diagnostics.Debug class for logging.
AddConsole(Action<LogConsumerBuilder<ConsoleLogConsumer>>? configure = null)
Adds the ConsoleLogConsumer instance that uses System.Console class for logging.
Extension methods from Atata.NUnit library
AddNUnitTestContext(Action<LogConsumerBuilder<ConsoleLogConsumer>>? configure = null)
Adds the NUnitTestContextLogConsumer instance that uses NUnit’s NUnit.Framework.TestContext class for logging.
Extension methods from Atata.NLog library
AddNLog(Action<LogConsumerBuilder<ConsoleLogConsumer>>? configure = null)
Adds the NLogConsumer instance that uses NLog.Logger class for logging.
AddNLogFile(Action<LogConsumerBuilder<ConsoleLogConsumer>>? configure = null)
Adds the NLogFileConsumer instance that uses NLog.Logger class for logging into file.
Logging configuration
The list of LogConsumerBuilder<TLogConsumer> methods to configure ILogConsumer:
WithSectionEnd(LogSectionEndOption logSectionEnd)
Sets the output option of log section end.
The default value is LogSectionEndOption.Include.
Other options are: LogSectionEndOption.IncludeForBlocks and LogSectionEndOption.Exclude.
If section end is excluded, instead of “Starting: {action}” and “Finished: {action} {time elapsed}”, just “{action}” is outputted.
WithMinLevel(LogLevel level)
Specifies the minimum level of the log event to write to the log. The default value is Trace.
WithNestingLevelIndent(string messageNestingLevelIndent)
Sets the nesting level indent.
The default value is "- ".
WithSectionStartPrefix(string sectionStartPrefix)
Sets the prefix of section start.
The default value is "> ".
WithSectionEndPrefix(string sectionEndPrefix)
Sets the prefix of section end.
The default value is "< ".
WithEmbedSessionLog(bool enable)
Sets a value indicating whether session log should be embedded
in AtataContext log hierarchy or it should follow its own hierarchy.
The default value is true.
WithEmbedSourceLog(bool enable)
Sets a value indicating whether source log should be embedded
in AtataContext log hierarchy or it should follow its own hierarchy.
The default value is false.
WithSkipCondition(TestResultStatusCondition skipCondition)
Sets the condition under which logging should be skipped depending on a test result status.
The default value is TestResultStatusCondition.None.
When set to a value other than TestResultStatusCondition.None, log entries are postponed
until the end of the test item, when test result status is resolved.
WithTargetScopes(AtataContextScopes scopes)
Sets the target scopes for which to apply the log consumer.
The default value is AtataContextScopes.All.
With(Action<TLogConsumer> configureConsumer)
Configures a log consumer of the builder.
Screenshots
The screenshots functionality can be configured through the methods of Screenshots property of WebDriverSessionBuilder.
builder.Sessions.AddWebDriver(x => x
//...
.Screenshots.UseFullPageOrViewportStrategy()
.Screenshots.UseFileNameTemplate("{screenshot-number:D2}..."));
Screenshot strategy is a way how a screenshot should be taken, basically it can either a viewport area or a full-page screenshot. By default, the viewport taking strategy is used.
The list of ScreenshotsWebDriverSessionBuilder methods:
UseWebDriverViewportStrategy()
Sets the WebDriver viewport (WebDriverViewportScreenshotStrategy) strategy for a screenshot taking.
UseWebDriverFullPageStrategy()
Sets the WebDriver full-page (WebDriverFullPageScreenshotStrategy) strategy for a screenshot taking.
Works only for FirefoxDriver.
UseCdpFullPageStrategy()
Sets the CDP full-page (CdpFullPageScreenshotStrategy) strategy for a screenshot taking.
Works only for ChromeDriver and EdgeDriver.
UseFullPageOrViewportStrategy()
Sets the “full-page or viewport” (FullPageOrViewportScreenshotStrategy) strategy for a screenshot taking.
UseStrategy(IScreenshotStrategy strategy)
Sets the strategy for a screenshot taking.
The default value is an instance of WebDriverViewportScreenshotStrategy.
UseFileNameTemplate(string fileNameTemplate)
Sets the file name template of page screenshots.
The default value is "{screenshot-number:D2}{screenshot-pageobjectname: *}{screenshot-pageobjecttypename: *}{screenshot-title: - *}".
UseFileNameTemplate(string fileNameTemplate)
Sets the file name template of page screenshots.
The default value is "{screenshot-pageobjectname}{screenshot-pageobjecttypename:_*}{screenshot-title:-*}".
UseFileNameTemplateWithSessionId()
Sets the file name template of page screenshots including {session-id} variable.
The set value is "{session-id}-{screenshot-pageobjectname}{screenshot-pageobjecttypename:_*}{screenshot-title:-*}".
UsePrependArtifactNumberToFileName(bool enable)
Sets a value indicating whether to prepend artifact number to file name in a form of “001-{file name}”.
The default value true.
UseTakeOnFailure(bool enable)
Sets a value indicating whether to take a screenshot on failure.
The default value true.
Page snapshots
The page snapshot functionality can be configured through the methods of PageSnapshots property of WebDriverSessionBuilder.
builder.Sessions.AddWebDriver(x => x
//...
.PageSnapshots.UseCdpStrategy()
.PageSnapshots.UseFileNameTemplate("{snapshot-number:D2}..."));
The default strategy is CdpOrPageSourcePageSnapshotStrategy.
The list of PageSnapshotsWebDriverSessionBuilder methods:
UseCdpOrPageSourceStrategy()
Sets the “CDP or page source” (CdpOrPageSourcePageSnapshotStrategy) strategy for a page snapshot taking.
UsePageSourceStrategy()
Sets the page source (PageSourcePageSnapshotStrategy) strategy for a page snapshot taking.
UseCdpStrategy()
Sets the CDP (CdpPageSnapshotStrategy) strategy for a page snapshot taking.
UseStrategy(IPageSnapshotStrategy strategy)
Sets the strategy for a page snapshot taking.
The default value is an instance of CdpOrPageSourcePageSnapshotStrategy.
UseFileNameTemplate(string fileNameTemplate)
Sets the file name template of page snapshots.
The default value is "{snapshot-pageobjectname}{snapshot-pageobjecttypename:_*}{snapshot-title:-*}".
UseFileNameTemplateWithSessionId()
Sets the file name template of page snapshots including {session-id} variable.
The set value is "{session-id}-{snapshot-pageobjectname}{snapshot-pageobjecttypename:_*}{snapshot-title:-*}".
UsePrependArtifactNumberToFileName(bool enable)
Sets a value indicating whether to prepend artifact number to file name in a form of “001-{file name}”.
The default value true.
UseTakeOnFailure(bool enable)
Sets a value indicating whether to take a page snapshot on failure.
The default value true.
Event subscriptions
Atata provides a set of events that are raised during execution.
Event handlers can be subscribed on Atata or custom events through the methods of EventSubscriptions property of AtataContextBuilder or AtataSessionBuilder<TSession, TBuilder>.
The list of Atata events:
AtataContextPreInitEventAtataContextInitStartedEventAtataContextInitCompletedEventAtataContextDeInitStartedEventAtataContextDeInitCompletedEventAtataSessionAssignedToContextEventAtataSessionUnassignedFromContextEventAtataSessionInitStartedEventAtataSessionInitCompletedEventAtataSessionDeInitStartedEventAtataSessionDeInitCompletedEventArtifactAddedEventPageObjectInitStartedEventPageObjectTransitionInCompletedEventPageObjectTransitionOutCompletedEventPageObjectInitCompletedEventPageObjectDeInitCompletedEventWebDriverInitCompletedEventWebDriverDeInitStartedEvent
Find more details on events and subscriptions on the Events page.
The list of methods of EventSubscriptionsBuilder<TRootBuilder>:
Add<TEvent> (Action eventHandler)
Add<TEvent> (Action<TEvent> eventHandler)
Add<TEvent> (Action<TEvent, AtataContext> eventHandler)
Add<TEvent> (Func<CancellationToken, Task> eventHandler)
Add<TEvent> (Func<TEvent, CancellationToken, Task> eventHandler)
Add<TEvent> (Func<TEvent, AtataContext, CancellationToken, Task> eventHandler)
Add<TEvent> (IEventHandler<TEvent> eventHandler)
Add<TEvent> (IAsyncEventHandler<TEvent> eventHandler)
Adds the specified event handler as a subscription to the TEvent.
Add<TEvent, TEventHandler> ()
where TEventHandler : class, IEventHandler<TEvent>, new()
Adds the created instance of TEventHandler as a subscription to the TEvent.
Add<TEvent> (Type eventType, Type eventHandlerType)
Adds the created instance of eventHandlerType as a subscription to the eventType.
Add<TEvent> (Type eventHandlerType)
Adds the created instance of eventHandlerType as a subscription to the event type
that is read from IEventHandler<TEvent> generic argument that eventHandlerType should implement.
RemoveAll (Predicate<EventSubscriptionItem> match)
Removes all the subscriptions that match the conditions defined by the specified predicate.
Usage
Add handler to AtataContext event:
builder.EventSubscriptions.Add<AtataContextInitCompletedEvent>(x => x.Context.Log.Info("Context created"));
Add handler to AtataSession event:
builder.Sessions.AddWebDriver(x => x
.UseChrome()
.EventSubscriptions.Add<WebDriverInitCompletedEvent>(x => x.Driver.Maximize()));
NUnit event handlers
The following event handlers are from Atata.NUnit package.
AddArtifactsToNUnitTestContext()
Defines that after AtataContext deinitialization the files stored in Artifacts directory
should be added to NUnit TestContext.
AddDirectoryFilesToNUnitTestContext(string directoryPath)
AddDirectoryFilesToNUnitTestContext(Func<string> directoryPathBuilder)
AddDirectoryFilesToNUnitTestContext(Func<AtataContext, string> directoryPathBuilder)
Defines that after AtataContext deinitialization the files stored in the
specified directory should be added to NUnit TestContext.
Directory path supports template variables.
Navigation
Go
A page object navigation starts with Go static class, or alternatively with Go property of WebDriverSession instance.
Both Go approaches provide a set of similar methods for navigation.
Go static class methods
To<T>(T pageObject = null, string url = null, bool navigate = true, bool temporarily = false)
where T : PageObject<T>Navigates to the specified page object.
On<T>()
where T : PageObject<T>Continues with the specified page object type.
Firstly, checks whether the current AtataContext.PageObject
is T, if it is, returns it;
otherwise, creates a new instance of T without navigation.
The method is useful in case when in a particular step method (BDD step, for example)
you don’t have an instance of current page object but you are sure that a browser is on the needed page.
OnRefreshed<T>()
where T : PageObject<T>Continues with the specified page object type with rage refresh.
Firstly, checks whether the current AtataContext.PageObject
is T, if it is, returns it;
otherwise, creates a new instance of T without navigation.
Then a page is refreshed.
The method is useful in case when you reuse a single test suite driver by tests and
want to refresh a page on start of each test to ensure that the page is in clean start state.
OnOrTo<T>()
where T : PageObject<T>Continues with the specified page object type or navigates to it.
Firstly, checks whether the current AtataContext.PageObject
is T, if it is, returns it; otherwise, creates a new instance of T with navigation.
The method is useful in case when in a particular step method (BDD step, for example)
you don’t have an instance of current page object and you are not sure that a browser is on the needed page, but can be.
ToWindow<T>(T pageObject, string windowName, bool temporarily = false)
where T : PageObject<T>Navigates to the window with the specified page object by name.
ToWindow<T>(string windowName, bool temporarily = false)
where T : PageObject<T>Navigates to the window by name.
ToNextWindow<T>(T pageObject = null, bool temporarily = false)
where T : PageObject<T>Navigates to the next window with the specified page object.
ToPreviousWindow<T>(T pageObject = null, bool temporarily = false)
where T : PageObject<T>Navigates to the previous window with the specified page object.
ToUrl(string url)
Navigates to the specified URL.
ToNewWindow<T>(T pageObject = null, string url = null, bool temporarily = false)
where T : PageObject<T>Navigates to a new window with the specified page object.
ToNewWindowAsTab<T>(T pageObject = null, string url = null, bool temporarily = false)
where T : PageObject<T>Navigates to a new tab window with the specified page object.
Usage
Go.To<HomePage>()
.Header.Should.Equal("Home");
Go.To<AboutPage>(url: "/about")
.Should.Equal("About");
By static URL
Every page object can have a static URL associated with it by UrlAttribute.
This URL is consumed during Go.To action to perform a navigation.
The URL can be an absolute, but it’s recommended to use a relative URL,
it will be concatenated with BaseUrl to form an absolute URL.
Example
[Url("/contact")]
public class ContactPage : Page<_>
{
}
Go.To<ContactPage>();
By dynamic URL
When a page object’s URL is dynamic (contains identifiers in path, query parameters, etc.), one of the following approaches can be used for assigning a dynamic URL to a page object.
Pass URL in Go.To method
Go.To<UserPage>(url: $"/user/{userId}");
SetNavigationUrl/AppendNavigationUrl methods
PageObject<TOwner> has functionality to set a navigation URL of the page object before navigation.
So you can set a dynamic URL in the constructor of page object or elsewhere before navigation.
Static URL (a value of UrlAttribute) can be combined with a dynamic URL part.
Example 1
Go.To(new UserPage().SetNavigationUrl($"/user/{id}"));
Example 2
public class UserPage : Page<_>
{
public UserPage(int? id = null)
{
if (id.HasValue)
SetNavigationUrl($"/user/{id}");
}
}
Go.To(new UserPage(42));
Example 3
public class UserPage : Page<_>
{
// Default constructor is needed for non-direct navigation, for example via link click.
public UserPage()
{
}
public UserPage(int id)
{
SetNavigationUrl($"/user/{id}");
}
}
Go.To(new UserPage(42));
Example 4
public class UserPage : Page<_>
{
public static _ ById(int id) =>
new _().SetNavigationUrl($"/user/{id}");
}
Go.To(UserPage.ById(42));
Example 5
Use AppendNavigationUrl instead of SetNavigationUrl to combine static URL with a dynamic part.
[Url("/search")]
public class GoogleSearchPage : Page<_>
{
public GoogleSearchPage(string? query = null)
{
if (query is not null)
AppendNavigationUrl($"?q={query}"); // "/search" + $"?q={query}" = "/search?q={query}"
}
}
Go.To<GoogleSearchPage>();
// Or:
Go.To(new GoogleSearchPage("keyword"));
Example 6
Similar to the previous example, but uses static method instead of constructor.
[Url("/search")]
public class GoogleSearchPage : Page<_>
{
public static _ WithQuery(string query) =>
new _().AppendNavigationUrl($"?q={query}");
}
Go.To<GoogleSearchPage>();
// Or:
Go.To(GoogleSearchPage.WithQuery("keyword"));
By combined URL
Go.To method’s url argument value combines with page object’s navigation URL data
if it starts with one of: ?, &, ;, #.
For other cases url argument value replaces the page object’s navigation URL.
Basically, you can combine static URL part with dynamic one.
Example
[Url("/some/path?a=1")]
public class SomePage : Page<_>
{
}
Go.To<SomePage>(url: "/another/path?b=2"); // -> "/another/path?b=2"
Go.To<SomePage>(url: "?b=2"); // -> "/some/path?b=2"
Go.To<SomePage>(url: "&b=2"); // -> "/some/path?a=1&b=2"
Go.To<SomePage>(url: ";b=2"); // -> "/some/path?a=1;b=2"
Go.To<SomePage>(url: "#fragment"); // -> "/some/path?a=1#fragment"
URL template variables
Template variables are allowed in UrlAttribute and Go.To method’s url parameter.
The URL can be represented in a template format, like "/organization/{OrganizationId}/".
The template is filled with AtataContext.Variables by using AtataContext.FillUriTemplateString(string) method.
In order to output a { use {{, and to output a } use }}.
Before navigation ensure that a variable is set in AtataContext.
Set variable directly into AtataContext
AtataContext.ResolveCurrent().Variables["OrganizationId"] = 42;
Set variable directly into session
AtataContext.ResolveCurrent().Sessions.Get<WebDriverSession>().Variables["OrganizationId"] = 42;
Set variable for AtataContext during configuration
builder.UseVariable("OrganizationId", 42);
Set variable for session during configuration
builder.Sessions.AddWebDriver(x => x
//...
.UseVariable("OrganizationId", 42));
Use template in UrlAttribute
[Url("/organization/{OrganizationId}/")]
public class OrganizationPage : Page<_>
{
}
Go.To<OrganizationPage>();
Use template within Go.To
Go.To<OrganizationPage>(url: "/organization/{OrganizationId}/");
Use template in page object’s navigation URL
[Url("/search")]
public class UserPage : Page<_>
{
public static _ ById(int id) =>
new _().SetNavigationUrl($"/organization/{{OrganizationId}}/user/{id}");
}
Notice that OrganizationId is wrapped with {{ and }} to output { and } in an interpolated string.
Go.To(UserPage.ById(42));
Transition
A transition from one page object to another is implemented via controls:
Button, Link and Clickable.
Also a transition can be specified via adding INavigable<,> interface to a custom control.
Example
For example, having 3 simple pages on a site:
- “Users” page with users table and “New” link that navigates to the “User Editor” page. Clicking on a user row redirects to the “User Details” page.
- “User Editor” page that contains “Name” input field and “Save” button that redirect back to “Users” page.
- “User Details” page containing the name of the user.
UsersPage.cs
using Atata;
namespace SampleApp.UITests;
using _ = UsersPage;
[Url("users")]
public class UsersPage : Page<_>
{
public Link<UserEditorPage, _> New { get; private set; }
public Table<UserTableRow, _> Users { get; private set; }
public class UserTableRow : TableRow<_>, INavigable<UserDetailsPage, _>
{
public Text<_> Name { get; private set; }
}
}
UserEditorPage.cs
using Atata;
namespace SampleApp.UITests;
using _ = UserEditorPage;
public class UserEditorPage : Page<_>
{
public TextInput<_> Name { get; private set; }
public Button<UsersPage, _> Save { get; private set; }
}
UserDetailsPage.cs
using Atata;
namespace SampleApp.UITests;
using _ = UserDetailsPage;
public class UserDetailsPage : Page<_>
{
public H1<_> Name { get; private set; }
}
Usage
string userName;
Go.To<UsersPage>()
.New.ClickAndGo() // Navigates to UserEditorPage.
.Name.SetRandom(out userName) // Sets the random value to Name field and stores it to userName variable.
.Save.ClickAndGo() // Clicking the Save button navigates back to UsersPage.
.Users.Rows[x => x.Name == userName].ClickAndGo() // Clicking the row navigates to UserDetailsPage.
.Name.Should.Equal(userName);
Reporting
Reporting in Atata Framework consists of logging and artifact files.
The testing artifacts can be: log files, screenshots, page snapshots, downloaded files, etc.
All artifact files can be placed to the AtataContext.Artifacts directory.
By default, as it is recommended to be, AtataContext.Artifacts directory is unique per test.
The default Artifacts path follows the template:
{working_directory}\artifacts\{tests_run_timestamp}\{namespace_subpath}\{test_suite_name}\{test_name}"
For example:
{project_directory}\bin\Debug\net10.0\artifacts\20260512T112506\SomeFeature\SomeTests\Test1
Atata by itself writes a lot of log entries during execution, but custom log entries and artifact files can be reported as well.
There is also Reporting to ExtentReports tutorial, which describes how to configure Atata reporting to ExtentReports.
IReport<TOwner> interface
The main interface for reporting is IReport<out TOwner>.
An instance of IReport<TOwner> can be got by Report property of either AtataContext, AtataSession, or PageObject<TOwner>.
AtataContext.ResolveCurrent().Report.Info("Hello world!");
Go.To<SomePage>()
.Report.Step("Doing some step", x => x
.SomeInput.Type("some text")
.SomeButton.Click())
.Report.Screenshot();
Methods
Trace(string message)
Writes a trace log message.
Debug(string message)
Writes a debug log message.
Info(string message)
Writes an informational log message.
Warn(Exception exception)
Warn(string message)
Warn(Exception exception, string message)
Writes a warning log message.
Error(Exception exception)
Error(string message)
Error(Exception exception, string message)
Writes an error log message.
Fatal(Exception exception)
Fatal(string message)
Fatal(Exception exception, string message)
Writes a critical log message.
Setup(string message, Action<TOwner> action)
Setup<TResult>(string message, Func<TOwner, TResult> function)
SetupAsync(string message, Func<TOwner, Task> action)
SetupAsync<TResult>(string message, Func<TOwner, Task<TResult>> function)
Executes the specified action/function and represents it in a log as a setup section with the specified message. The setup action time is not counted as a “Test body” execution time, but counted as “Setup” time.
Step(string message, Action<TOwner> action)
Step<TResult>(string message, Func<TOwner, TResult> function)
StepAsync(string message, Func<TOwner, Task> action)
StepAsync<TResult>(string message, Func<TOwner, Task<TResult>> function)
Executes the specified action/function and represents it in a log as a section with the specified message.
IWebSessionReport<TOwner> interface
IWebSessionReport<out TOwner> interface instance is returned by Report property of WebSession and WebDriverSession classes.
It inherits from IReport<TOwner> interface and adds some methods related to web sessions, such as taking screenshots and page snapshots.
Methods
Screenshot(string title = null)
Takes a screenshot of the current page with an optionally specified title.
Screenshot(ScreenshotKind kind, string title = null)
Takes a screenshot of the current page of a certain kind with an optionally specified title.
PageSnapshot(string title = null)
Takes a snapshot (HTML or MHTML file) of the current page with an optionally specified title.
PageObjectReportExtensions class
PageObjectReportExtensions class contains an extension method for IReport<TOwner> interface, which is related to page objects.
Methods
Setup<TPageObject>(Func<TOwner, TPageObject> function)
Executes the specified function and represents it in a log as a setup section with the message like "Set up "<Some>" page".
The setup function time is not counted as a “Test body” execution time, but counted as “Setup” time.
Screenshots taking
Take a look at Getting Started / Configuration / Screenshots on how to configure the functionality.
There are few ways to capture a screenshot depending on place where you need to do it.
Take in test or page object
Use Report.Screenshot(...) method:
Go.To<OrdinaryPage>()
.Report.Screenshot();
//.Report.Screenshot("optional title"); // To specify a title.
//.Report.Screenshot(ScreenshotKind.FullPage); // To specify a kind (FullPage/Viewport).
Take in any place
WebDriverSession.Current!.TakeScreenshot();
WebDriverSession.Current!.Report.Screenshot();
Take using trigger
Use TakeScreenshot trigger. Below are just 2 possible scenarios.
Before button click
[TakeScreenshot(TriggerEvents.BeforeClick)]
// [TakeScreenshot("optional title", TriggerEvents.BeforeClick)] // To specify a title.
// [TakeScreenshot(ScreenshotKind.FullPage, TriggerEvents.BeforeClick)] // To specify a kind.
public Button<_> Save { get; private set; }
Upon page object initialization
[TakeScreenshot(TriggerEvents.Init)]
public class SomePage : Page<_>
{
}
Full-page screenshots
There is a possibility to take full-page screenshots. The functionality is not enabled by default. Also, currently it works only for Chrome, Edge and Firefox, so enable it carefully.
Enable full-page screenshots by default
Full-page screenshots can be enabled to be taken by default instead of viewport screenshots.
Configuration
Use Screenshots property of WebDriverSessionBuilder:
public ScreenshotsWebDriverSessionBuilder Screenshots { get; }
ScreenshotsWebDriverSessionBuilder contains the following methods:
// Used by default.
public WebDriverSessionBuilder UseWebDriverViewportStrategy();
// Works only for Firefox.
public WebDriverSessionBuilder UseWebDriverFullPageStrategy();
// Works only for Chrome and Edge.
public WebDriverSessionBuilder UseCdpFullPageStrategy();
// *** Recommended to use for full-page screenshots, regardless of browser/driver.
public WebDriverSessionBuilder UseFullPageOrViewportStrategy();
// To use custom strategy.
public WebDriverSessionBuilder UseStrategy(IScreenshotStrategy strategy);
Usage
builder.Sessions.AddWebDriver(x => x
//...
.Screenshots.UseFullPageOrViewportStrategy());
Explicitly take full-page screenshots
It is also possible to take full-page screenshots only at certain points.
It is allowed to explicitly specify ScreenshotKind enum value depending whether you need a viewport or a full-page screenshot.
ScreenshotKind enum provides 3 values: Default, Viewport and FullPage.
Examples
WebDriverSession.Current!.TakeScreenshot(ScreenshotKind.FullPage);
Go.To<SomePage>()
.Report.Screenshot(ScreenshotKind.FullPage);
[TakeScreenshot(ScreenshotKind.FullPage, TriggerEvents.Init)]
Page snapshots taking
A page snapshot can be either HTML or MHTML file.
For Chromium-based browsers (Chrome and Edge) a snapshot by default is taken using CDP command Page.captureSnapshot and saved as .MHTML file with styles and images.
Note that Page.captureSnapshot command is in experimental state
so the result page snapshot may not 100% be equal to an original page.
For other browsers a snapshot is taken using IWebDriver.PageSource property
and saved as .HTML file without styles.
Take a look at Getting Started / Configuration / Page Snapshots on how to configure the functionality.
There are few ways to capture a page snapshot depending on place where you need to do it.
Take in test or page object
Use Report.PageSnapshot(...) method:
Go.To<OrdinaryPage>()
.Report.PageSnapshot();
//.Report.PageSnapshot("optional title"); // To specify a title.
Take in any place
WebDriverSession.Current!.TakePageSnapshot();
WebDriverSession.Current!.Report.PageSnapshot();
Take using trigger
Use TakePageSnapshot trigger. Below are just 2 possible scenarios.
Before button click
[TakePageSnapshot(TriggerEvents.BeforeClick)]
// [TakePageSnapshot("optional title", TriggerEvents.BeforeClick)] // To specify a title.
public Button<_> Save { get; private set; }
Upon page object initialization
[TakePageSnapshot(TriggerEvents.Init)]
public class SomePage : Page<_>
{
}
Browser logs monitoring
Currently this functionality is available only for Chrome and Edge, both local and remote.
The feature brings a monitoring of browser logs, such as warnings and errors, which happen during a test execution. Browser logs can be transferred to Atata logs and can raise warnings.
In order to enable browser logs monitoring, configure AtataContext in the following way:
builder.Sessions.AddWebDriver(x => x
//...
.BrowserLogs.UseLog()
.BrowserLogs.UseMinLevelOfWarning(LogLevel.Warn));
UseLog(bool enable = true) - sets a value indicating whether the browser log should be transferred to Atata logging system. The default value is false.
UseMinLevelOfWarning(LogLevel? minLevel) - sets the minimum log level on which to raise warnings. The default value is null, meaning that warning is disabled. For example, setting the LogLevel.Warn value will mean to warn on browser log entries with LogLevel.Warn level and higher, which are LogLevel.Error and LogLevel.Fatal.
A log entry in Atata log can look like:
00:00:04.059 p0oG TRACE {Browser} http://localhost:54321/browserlogs 17:10 Uncaught Error: Some thrown error.
A warning looks this way:
Unexpected browser log error on "<ordinary>" page:
http://localhost:54321/browserlogs 17:10 Uncaught Error: Some thrown error.
JavaScript popup boxes
The fluent API for handling JavaScript popup boxes (alert, confirm, prompt).
The base PageObject<TOwner> class has 3 methods for different popup boxes:
public AlertBox<TOwner> SwitchToAlertBox(TimeSpan? waitTimeout = null, TimeSpan? waitRetryInterval = null);
public ConfirmBox<TOwner> SwitchToConfirmBox(TimeSpan? waitTimeout = null, TimeSpan? waitRetryInterval = null);
public PromptBox<TOwner> SwitchToPromptBox(TimeSpan? waitTimeout = null, TimeSpan? waitRetryInterval = null);
The methods wait and switch to the open popup box. By default, if waitTimeout and waitRetryInterval arguments are not specified, the AtataContext.WaitingTimeout and AtataContext.WaitingRetryInterval values are used correspondingly. If popup box does not appear within the specified time, the TimeoutException is thrown.
Alert
Go.To<SomePage>()
.AlertButton.Click()
.SwitchToAlertBox()
.Accept();
Confirm
Go.To<SomePage>()
.ConfirmButton.Click()
.SwitchToConfirmBox()
.Accept(); // or Cancel()
Prompt
Go.To<SomePage>()
.PromptButton.Click()
.SwitchToPromptBox()
.Type("Some text")
.Accept(); // or Cancel()
Verify popup text
Use Text property of popup box classes to get or verify the text of popup.
page.SwitchToAlertBox()
.Text.Should.Be("Some text");
Events
The events functionality allows to subscribe to Atata built-in and custom events as well as publish events.
EventBus
The core of the functionality is IEventBus interface,
which can used to subscribe to and publish events at any time of test cycle.
The IEventBus object is accessible through the EventBus property of AtataContext.
IEventBus provides the following methods:
void Publish<TEvent>(TEvent eventData);
Task PublishAsync<TEvent>(TEvent eventData);
Task PublishAsync<TEvent>(TEvent eventData, CancellationToken cancellationToken);
object Subscribe<TEvent>(Action eventHandler);
object Subscribe<TEvent>(Action<TEvent> eventHandler);
object Subscribe<TEvent>(Action<TEvent, AtataContext> eventHandler);
object Subscribe<TEvent>(Func<CancellationToken, Task> eventHandler);
object Subscribe<TEvent>(Func<TEvent, CancellationToken, Task> eventHandler);
object Subscribe<TEvent>(Func<TEvent, AtataContext, CancellationToken, Task> eventHandler);
object Subscribe<TEvent, TEventHandler>()
where TEventHandler : class, IEventHandler<TEvent>, new();
object Subscribe<TEvent>(IEventHandler<TEvent> eventHandler);
object Subscribe<TEvent>(IAsyncEventHandler<TEvent> eventHandler);
void Unsubscribe(object subscription);
void UnsubscribeHandler(object eventHandler);
void UnsubscribeAll<TEvent>();
void UnsubscribeAll(Type eventType);
void UnsubscribeAll();
IEventHandler
The event handler interface to implement for event handler classes:
public interface IEventHandler<in TEvent>
{
void Handle(TEvent eventData, AtataContext context);
}
IAsyncEventHandler
The event handler interface to implement for async event handler classes:
public interface IAsyncEventHandler<in TEvent>
{
Task HandleAsync(TEvent eventData, AtataContext context, CancellationToken cancellationToken);
}
IConditionalEventHandler
The event handler interface to implement for conditional event handler classes:
public interface IConditionalEventHandler<in TEvent> : IEventHandler<TEvent>
{
bool CanHandle(TEvent eventData, AtataContext context);
}
IConditionalAsyncEventHandler
The event handler interface to implement for conditional async event handler classes:
public interface IConditionalAsyncEventHandler<in TEvent> : IAsyncEventHandler<TEvent>
{
bool CanHandle(TEvent eventData, AtataContext context);
}
EventSubscriptionsBuilder<TRootBuilder>
EventSubscriptionsBuilder<TRootBuilder> - a base abstract builder of event subscriptions.
Its inherited classes are:
AtataContextEventSubscriptionsBuilder- available throughEventSubscriptionsproperty ofAtataContextBuilder.AtataSessionEventSubscriptionsBuilder<TSessionBuilder>- available throughEventSubscriptionsproperty ofAtataSessionBuilder<TSession, TBuilder>.
The base builder class provides methods to subscribe to Atata and custom events.
Methods
public TRootBuilder Add<TEvent>(Action eventHandler);
public TRootBuilder Add<TEvent>(Action<TEvent> eventHandler);
public TRootBuilder Add<TEvent>(Action<TEvent, AtataContext> eventHandler);
public TRootBuilder Add<TEvent>(Func<CancellationToken, Task> eventHandler);
public TRootBuilder Add<TEvent>(Func<TEvent, CancellationToken, Task> eventHandler);
public TRootBuilder Add<TEvent>(Func<TEvent, AtataContext, CancellationToken, Task> eventHandler);
public TRootBuilder Add<TEvent, TEventHandler>()
where TEventHandler : class, new();
public TRootBuilder Add<TEvent>(IEventHandler<TEvent> eventHandler);
public TRootBuilder Add<TEvent>(IAsyncEventHandler<TEvent> eventHandler);
public TRootBuilder Add(Type eventHandlerType);
public TRootBuilder Add(Type eventType, Type eventHandlerType);
public TRootBuilder RemoveAll(Predicate<EventSubscriptionItem> match);
AtataContextEventSubscriptionsBuilder contains one additional method that give an ability so subscribe on events for specified scopes only:
public EventSubscriptionsBuilder<AtataContextBuilder> For(AtataContextScopes scopes);
Usage
Subscribe action event handler
builder.EventSubscriptions.Add<WebDriverInitCompletedEvent>(e => e.Driver.Maximize());
Subscribe action event handler as a method
A method can have no parameters, single event type parameter, or event type parameter with AtataContext parameter.
Examples:
private static void OnWebDriverInitCompleted()
{
}
private static void OnWebDriverInitCompleted(WebDriverInitCompletedEvent eventData)
{
}
private static void OnWebDriverInitCompleted(WebDriverInitCompletedEvent eventData, AtataContext context)
{
}
Then subscribe it:
builder.EventSubscriptions.Add<WebDriverInitCompletedEvent>(OnWebDriverInitCompleted);
Create and subscribe specific event handler class
Create an event handler class, for example for WebDriverInitCompletedEvent:
public class WebDriverInitCompletedEventHandler : IEventHandler<WebDriverInitCompletedEvent>
{
public void Handle(WebDriverInitCompletedEvent eventData, AtataContext context)
{
// TODO: Implement.
}
}
Subscribe it during AtataContext building:
builder.EventSubscriptions.Add(new WebDriverInitCompletedEventHandler());
Create and subscribe universal event handler class
Create a universal event handler class, which can be used to subscribe to any event type:
private class UniversalEventHandler : IEventHandler<object>
{
public void Handle(object eventData, AtataContext context)
{
// TODO: Implement.
}
}
Subscribe it during AtataContext building to different events:
builder
.EventSubscriptions.Add<WebDriverInitCompletedEvent>(new UniversalEventHandler())
.EventSubscriptions.Add<AtataContextInitCompletedEvent>(new UniversalEventHandler());
Built-in events
AtataContext events
AtataContextPreInitEvent- occurs beforeAtataContextinitialization.AtataContextInitStartedEvent- occurs whenAtataContextis started to initialize.AtataContextInitCompletedEvent- occurs whenAtataContextis initialized.AtataContextDeInitStartedEvent- occurs whenAtataContextis started to deinitialize.AtataContextDeInitCompletedEvent- occurs whenAtataContextis deinitialized.
AtataSession events
AtataSessionAssignedToContextEvent- occurs whenAtataSessionis assigned toAtataContext.AtataSessionUnassignedFromContextEvent- occurs whenAtataSessionis unassigned fromAtataContext.AtataSessionInitStartedEvent- occurs whenAtataSessionis started to initialize.AtataSessionInitCompletedEvent- occurs whenAtataSessionis initialized.AtataSessionDeInitStartedEvent- occurs whenAtataSessionis started to deinitialize.AtataSessionDeInitCompletedEvent- occurs whenAtataSessionis deinitialized.
Artifact events
ArtifactAddedEvent- occurs when an artifact file is saved.
PageObject events
PageObjectInitStartedEvent- occurs whenPageObject<TOwner>is started to initialize.PageObjectTransitionInCompletedEvent- occurs whenPageObject<TOwner>transition in is completed. That is, navigation to the current page object occurred in the same browser tab by interacting with the previous page object, rather than by directly navigating to a URL.PageObjectTransitionOutCompletedEvent- occurs whenPageObject<TOwner>transition out is completed. That is, navigation to the next page object occurred in the same browser tab by interacting with the current page object, rather than by directly navigating to a URL.PageObjectInitCompletedEvent- occurs whenPageObject<TOwner>is initialized.PageObjectDeInitCompletedEvent- occurs whenPageObject<TOwner>is deinitialized.
WebDriver events
WebDriverInitCompletedEvent- occurs whenWebDriverSession.Driveris initialized.WebDriverDeInitStartedEvent- occurs whenWebDriverSession.Driveris started to deinitialize.