Getting Started

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.

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.
  • 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().

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 default IWebElement.Click() way.
    • Settings attributes - set settings for control finding, culture, value format, etc.

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 Log and Report properties.
  • 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 AtataContextBuilder together 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

  • Artifacts to work with the directory as an Atata DirectorySubject.
  • ArtifactsPath to get the full physical path.
  • ArtifactsRelativePath to 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 FileSubject for 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 from ArtifactTypes or 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:

  • Trace
  • Debug
  • Info
  • Warn
  • Error
  • Fatal

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>();

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 Java WebDriverManager.
  • 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

  1. When you create a test project, the core package which you need is Atata.
  2. 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.
  3. Atata.NLog is recommended to enable logging to files. It is useful for debugging and analyzing test failures, especially on CI pipelines.
  4. 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).
  5. 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.
  6. In case of local web UI testing, Atata.WebDriverSetup is recommended to set up browser drivers locally.
  7. If you want to validate HTML pages, consider adding Atata.HtmlValidation.

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:

  1. Go to File/New/Project… or File/Add/New Project… (to add to existing solution).
  2. Type Atata into search box or choose Atata in “project types” drop-down.
  3. Choose template, e.g., Atata NUnit Advanced Test Project (.NET 10), and specify project name and location.

Atata Templates project

Project references

The project is created with NuGet package references:

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

  1. Create a project using one of the project templates: “Atata NUnit Basic Test Project (.NET 8)”, “Atata NUnit Advanced Test Project (.NET 8)”.
  2. Open project .csproj file.
  3. Change the value of <TargetFramework> tag from net8.0 to 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:

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.

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 Email and Password controls is performed by label. Can be changed/configured.
  • Default search of SignIn button 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 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());

    //...
}

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

public AtataSessionsBuilder

Sessions { get; }

Gets the builder of sessions, which provides the functionality to add/configure/remove sessions and session providers.

public AttributesBuilder

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.

public AtataContextEventSubscriptionsBuilder

EventSubscriptions { get; }

Gets the builder of event subscriptions, which provides the methods to subscribe to Atata and custom events.

public LogConsumersBuilder

LogConsumers { get; }

Gets the builder of log consumers, which provides the methods to add log consumers.

public AtataContextBuilder

Use(Action<AtataContextBuilder> configure)

Configures this builder by action delegate.

public AtataContextBuilder

UseParentContext(AtataContext? parentContext)

Sets the parent context.

public AtataContextBuilder

UseVariable(string key, object? value)

Sets the variable.

public AtataContextBuilder

UseVariables(IEnumerable<KeyValuePair<string, object?>> variables)

Sets the variables.

public AtataContextBuilder

UseState<TValue>(TValue value)

Sets the state object.

public AtataContextBuilder

UseState(string key, object? value)

Sets the state object.

public AtataContextBuilder

UseState(IEnumerable<KeyValuePair<string, object?>> objects)

Sets the state objects.

public AtataContextBuilder

AddSecretStringToMaskInLog(string value, string mask = "{*****}")

Adds the secret string to mask in log.

public AtataContextBuilder

UseTestName(string? testName)

Sets the name of the test.

public AtataContextBuilder

UseTestName(Func<string?> testNameFactory)

Sets the factory method of the test name.

public AtataContextBuilder

UseTestSuiteName(string? testSuiteName)

Sets the name of the test suite (class).

public AtataContextBuilder

UseTestSuiteName(Func<string?> testSuiteNameFactory)

Sets the factory method of the test suite (class) name.

public AtataContextBuilder

UseTestSuiteType(Type? testSuiteType)

Sets the type of the test suite class.

public AtataContextBuilder

UseTestSuiteType(Func<Type?> testSuiteTypeFactory)

Sets the factory method of the test suite class type.

public AtataContextBuilder

UseTestSuiteGroupName(string? testSuiteGroupName)

Sets the name of the test suite group (collection fixture).

public AtataContextBuilder

UseTestSuiteGroupName(Func<string?> testSuiteGroupNameFactory)

Sets the factory method of the test suite group (collection fixture) name.

public AtataContextBuilder

UseTestTraits(IReadOnlyList<TestTrait>? testTraits)

Sets the test traits.

public AtataContextBuilder

UseTestTraits(Func<IReadOnlyList<TestTrait>?> testTraitsFactory)

Sets the factory method of the test traits.

public AtataContextBuilder

UseBaseRetryTimeout(TimeSpan timeout)

Sets the base retry timeout. The default value is 5 seconds.

public AtataContextBuilder

UseBaseRetryInterval(TimeSpan interval)

Sets the base retry interval. The default value is 200 milliseconds.

public AtataContextBuilder

UseWaitingTimeout(TimeSpan timeout)

Sets the waiting timeout. The default value is taken from BaseRetryTimeout, which is equal to 5 seconds by default.

public AtataContextBuilder

UseWaitingRetryInterval(TimeSpan interval)

Sets the waiting retry interval. The default value is taken from BaseRetryInterval, which is equal to 200 milliseconds by default.

public AtataContextBuilder

UseVerificationTimeout(TimeSpan timeout)

Sets the verification timeout. The default value is taken from BaseRetryTimeout, which is equal to 5 seconds by default.

public AtataContextBuilder

UseVerificationRetryInterval(TimeSpan interval)

Sets the verification retry interval. The default value is taken from BaseRetryInterval, which is equal to 200 milliseconds by default.

public AtataContextBuilder

UseDefaultCancellationToken(CancellationToken cancellationToken)

Sets the default cancellation token. The default value is CancellationToken.None.

public AtataContextBuilder

UseCulture(CultureInfo culture)

Sets the culture. The default value is CultureInfo.CurrentCulture.

public AtataContextBuilder

UseCulture(string cultureName)

Sets the culture by the name. The default value is CultureInfo.CurrentCulture.

public AtataContextBuilder

UseAssertionExceptionFactory(IAssertionExceptionFactory factory)

Sets the assertion exception factory. The default value is an instance of AtataAssertionExceptionFactory.

public AtataContextBuilder

UseAggregateAssertionExceptionFactory(IAggregateAssertionExceptionFactory factory)

Sets the aggregate assertion strategy.

public AtataContextBuilder

UseAggregateAssertionStrategy(IAggregateAssertionStrategy strategy)

Sets the aggregate assertion strategy. The default value is an instance of AtataAggregateAssertionStrategy.

public AtataContextBuilder

UseWarningReportStrategy(IWarningReportStrategy strategy)

Sets the strategy for warning assertion reporting. The default value is an instance of AtataWarningReportStrategy.

public AtataContextBuilder

UseAssertionFailureReportStrategy(IAssertionFailureReportStrategy strategy)

Sets the strategy for assertion failure reporting. The default value is an instance of AtataAssertionFailureReportStrategy.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

Clone()

Creates a copy of the current builder.

public AtataContextBuilder

CloneFor(AtataContextScope scope)

Creates a copy of the current builder for the specified scope.

public AtataContext

Build(CancellationToken cancellationToken = default)

public Task<AtataContext>

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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:

public AtataContextGlobalProperties

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}
public AtataContextGlobalProperties

UseDefaultArtifactsRootPathTemplateIncludingRunStart(string include)

Sets the default Artifacts Root path template with optionally including "{run-start:yyyyMMddTHHmmss}" folder in the path.

public AtataContextGlobalProperties

UseDefaultArtifactsRootPathTemplateExcludingRunStartOnCI()

Sets the default Artifacts Root path template excluding "{run-start:yyyyMMddTHHmmss}" folder in the path on CI environment.

public AtataContextGlobalProperties

UseArtifactsPathFactory(IArtifactsPathFactory artifactsPathFactory)

Sets the artifacts path factory.

public AtataContextGlobalProperties

UseRootNamespaceOf(string? rootNamespace)

Sets the root namespace.

public AtataContextGlobalProperties

UseRootNamespaceOf<T>()

Sets the root namespace with the namespace of the specified T type.

public AtataContextGlobalProperties

UseRootNamespaceOf(Type type)

Sets the root namespace with the namespace of the specified type.

public AtataContextGlobalProperties

UseTimeZone(TimeZoneInfo timeZone)

Sets the time zone.

public AtataContextGlobalProperties

UseTimeZone(string timeZoneId)

Sets the time zone by identifier, which corresponds to the TimeZoneInfo.Id property.

public AtataContextGlobalProperties

UseUtcTimeZone()

Sets the UTC time zone.

public AtataContextGlobalProperties

UseModeOfCurrent(AtataContextModeOfCurrent mode)

Sets the mode of AtataContext.Current property. The default value is AtataContextModeOfCurrent.AsyncLocal.

public AtataContextGlobalProperties

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.

public AtataContextGlobalProperties

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

public AtataContextBuilder

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.

public AtataContextBuilder

Add(IAtataSessionProvider sessionProvider)

Adds the specified session provider.

public AtataContextBuilder

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 the AtataSessionBuilderNotFoundException if 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.
public AtataContextBuilder

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 the AtataSessionBuilderNotFoundException if 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.
public AtataContextBuilder

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 the AtataSessionBuilderNotFoundException if 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.
public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

Remove(IAtataSessionProvider sessionProvider)

Removes the specified session provider.

public AtataContextBuilder

RemoveAll<TSessionBuilder>()

where TSessionBuilder : IAtataSessionBuilder

Removes all session providers of the specified TSessionProvider type.

public AtataContextBuilder

RemoveAll<TSessionBuilder>(string? name)

where TSessionBuilder : IAtataSessionBuilder

Removes all session providers of the specified TSessionProvider type and name.

public AtataContextBuilder

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.

public AtataContextBuilder

RemoveAllBySessionType<TSession>()

Removes all session providers of the specified TSession session type regardless of name.

public AtataContextBuilder

RemoveAllBySessionType<TSession>(string? name)

Removes all session providers of the specified TSession session type and name.

public AtataContextBuilder

RemoveAllBySessionType(Type sessionType)

Removes all session providers of the specified sessionType session type regardless of name.

public AtataContextBuilder

RemoveAllBySessionType(Type sessionType, string? name)

Removes all session providers of the specified sessionType session type and name.

public AtataContextBuilder

RemoveAllBySessionName(string name)

Removes all session providers with the specified name.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

Clear()

Clears all session providers.

AtataSessionsBuilder extension methods for WebDriver sessions

public AtataContextBuilder

AddWebDriver(Action<WebDriverSessionBuilder>? configure = null)

Adds a new instance of WebDriverSessionBuilder builder.

public AtataContextBuilder

ConfigureWebDriver(Action<WebDriverSessionBuilder> configure, ConfigurationMode mode = default)

Configures existing nameless WebDriverSessionBuilder session builder.

public AtataContextBuilder

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 an AtataSession.
    • 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

public TBuilder

Use(Action<TBuilder> configure)

Configures this builder by action delegate.

public TBuilder

UseName(string? name)

Sets the Name value for a session.

public TBuilder

UseStartScopes(AtataContextScopes startScopes)

Sets the StartScopes (the scopes for which an AtataSession should automatically start) value for a session.

public TBuilder

UseStart(bool start = true)

Sets the StartScopes value for a session with either AtataContextScopes.All or AtataContextScopes.None, depending on the start parameter.

public TBuilder

UseStartCondition(Func<AtataContext, bool> predicate)

public TBuilder

UseStartCondition(Func<AtataContext, Task<bool>> predicate)

public TBuilder

UseStartCondition(Func<AtataContext, ValueTask<bool>> predicate)

Adds a start condition predicate that determines whether the session should be started for the provided AtataContext.

public TBuilder

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

public TBuilder

AddDependentConfiguration<TOtherSession>(Action<TOtherSession> configure)

where TOtherSession : AtataSession
public TBuilder

AddDependentConfiguration<TOtherSession>(Action<TBuilder, TOtherSession> configure)

where TOtherSession : AtataSession
public TBuilder

AddDependentConfiguration<TOtherSession>(string? sessionName, Action<TOtherSession> configure)

where TOtherSession : AtataSession
public TBuilder

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.

public TBuilder

AddDynamicConfiguration(Action<TBuilder> configure)

public TBuilder

AddDynamicConfiguration(Action<TBuilder, AtataContext> configure)

Adds the specified dynamic configuration action. This action will be executed when the session is building.

public TBuilder

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.

public TBuilder

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.

public TBuilder

UseAsOwn()

Sets the session mode to AtataSessionMode.Own (the default mode).

public TBuilder

UseAsShared()

Sets the session mode to AtataSessionMode.Shared.

public TBuilder

UseAsPool(Action<AtataSessionPoolBuilder>? configure = null)

Sets the session mode to AtataSessionMode.Pool and optionally configures the session pool.

public TBuilder

UseVariable(string key, object value)

Sets the variable.

public TBuilder

UseVariables(IEnumerable<KeyValuePair<string, object>> variables)

Sets the variables.

public TBuilder

UseState<TValue>(TValue value)

public TBuilder

UseState(string key, object value)

Sets the state object.

public TBuilder

UseState(IEnumerable<KeyValuePair<string, object>> variables)

Sets the state objects.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

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.

public AtataContextBuilder

UseSessionWaitingTimeout(TimeSpan timeout)

Sets the session waiting timeout, which is used in session borrowing and getting from pool. The default value is 5 minutes.

public AtataContextBuilder

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.

public Task<TSession>

BuildAsync(CancellationToken cancellationToken = default)

Builds the session within a target AtataContext, AtataContext.Current, or creates a temporary default non-scoped context.

AtataSessionRequestBuilder<TBuilder> methods

public TBuilder

UseStartCount(int count)

Sets the StartCount value, the count of sessions to request on startup. The default value is 1.

public TBuilder

UseStartMultipleInParallel(bool enable)

Sets the StartMultipleInParallel value, the count of sessions to request on startup. The default value is 1.

AtataSessionPoolRequestBuilder methods

public AtataSessionPoolRequestBuilder

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

public TBuilder

UseBaseUrl(string? baseUrl)

public TBuilder

UseBaseUrl(Uri? baseUrl)

Sets the base URL.

public TBuilder

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.

public TBuilder

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.

public TBuilder

UseDomTestIdAttributeName(string name)

Sets the name of the DOM test identifier attribute. The default value is "data-testid".

public TBuilder

UseDomTestIdAttributeDefaultCase(TermCase defaultCase)

Sets the default case of the DOM test identifier attribute. The default value is TermCase.Kebab.

public TBuilder

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

public WebDriverSessionBuilder

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.

public WebDriverSessionBuilder

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.

public WebDriverSessionBuilder

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.

public WebDriverSessionBuilder

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.

public WebDriverSessionBuilder

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.

public WebDriverSessionBuilder

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.

public WebDriverSessionBuilder

ConfigureChrome(Action<ChromeDriverBuilder>? configure = null)

Configures an existing or creates a new builder for ChromeDriver with default WebDriverAliases.Chrome alias.

public WebDriverSessionBuilder

ConfigureChrome(string alias, Action<ChromeDriverBuilder>? configure = null)

Configures an existing or creates a new builder for ChromeDriver with the specified alias.

public WebDriverSessionBuilder

ConfigureFirefox(Action<FirefoxDriverBuilder>? configure = null)

Configures an existing or creates a new builder for FirefoxDriver with default WebDriverAliases.Firefox alias.

public WebDriverSessionBuilder

ConfigureFirefox(string alias, Action<FirefoxDriverBuilder>? configure = null)

Configures an existing or creates a new builder for FirefoxDriver with the specified alias.

public WebDriverSessionBuilder

ConfigureInternetExplorer(Action<InternetExplorerDriverBuilder>? configure = null)

Configures an existing or creates a new builder for InternetExplorerDriver with default WebDriverAliases.InternetExplorer alias.

public WebDriverSessionBuilder

ConfigureInternetExplorer(string alias, Action<InternetExplorerDriverBuilder>? configure = null)

Configures an existing or creates a new builder for InternetExplorerDriver with the specified alias.

public WebDriverSessionBuilder

ConfigureEdge(Action<EdgeDriverBuilder>? configure = null)

Configures an existing or creates a new builder for EdgeDriver with default WebDriverAliases.Edge alias.

public WebDriverSessionBuilder

ConfigureEdge(string alias, Action<EdgeDriverBuilder>? configure = null)

Configures an existing or creates a new builder for EdgeDriver with the specified alias.

public WebDriverSessionBuilder

ConfigureSafari(Action<SafariDriverBuilder>? configure = null)

Configures an existing or creates a new builder for SafariDriver with default WebDriverAliases.Safari alias.

public WebDriverSessionBuilder

ConfigureSafari(string alias, Action<SafariDriverBuilder>? configure = null)

Configures an existing or creates a new builder for SafariDriver with the specified alias.

public WebDriverSessionBuilder

ConfigureRemoteDriver(Action<RemoteWebDriverBuilder>? configure = null)

Configures an existing or creates a new builder for RemoteWebDriver with default WebDriverAliases.Remote alias.

public WebDriverSessionBuilder

ConfigureRemoteDriver(string alias, Action<RemoteWebDriverBuilder>? configure = null)

Configures an existing or creates a new builder for RemoteWebDriver with the specified alias.

public WebDriverSessionBuilder

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.

public WebDriverSessionBuilder

UseDriver<TDriverBuilder>(Action<TDriverBuilder>? configure = null)

where TDriverBuilder : WebDriverBuilder<TDriverBuilder>, new()
public WebDriverSessionBuilder

UseDriver<TDriverBuilder>(TDriverBuilder driverBuilder, Action<TDriverBuilder>? configure = null)

where TDriverBuilder : WebDriverBuilder<TDriverBuilder>

Use the driver builder.

public WebDriverSessionBuilder

UseDriver(string alias)

Sets the driver to use by the specified alias.

public WebDriverSessionBuilder

UseDriver(IWebDriver driver, Action<CustomWebDriverBuilder>? configure = null)

Use the specified driver instance.

public WebDriverSessionBuilder

UseDriver(Func<IWebDriver> driverFactory, Action<CustomWebDriverBuilder>? configure = null)

Use the custom driver factory method.

public WebDriverSessionBuilder

UseDisposeDriver(bool disposeDriver)

Sets a value indicating whether to dispose the WebDriverSession.Driver when AtataSession.DisposeAsync method is invoked. The default value is true.

public WebDriverSessionBuilder

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.

public {DriverBuilder}

WithArguments(params string[] arguments)

public {DriverBuilder}

WithArguments(IEnumerable<string> arguments)

Adds arguments to be appended to the browser executable command line.

public {DriverBuilder}

WithAlias(string alias)

Specifies the driver alias.

public {DriverBuilder}

WithDownloadDirectory(string directoryPath)

Adds the download.default_directory user profile preference to options with the value specified by directoryPath.

public {DriverBuilder}

WithDownloadDirectory(Func<string> directoryPathBuilder)

Adds the download.default_directory user profile preference to options with the value specified by directoryPathBuilder.

public {DriverBuilder}

WithArtifactsAsDownloadDirectory()

Adds the download.default_directory user profile preference to options with the value of Artifacts directory path.

public {DriverBuilder}

WithOptions{DriverOptions} options)

Specifies the driver options.

public {DriverBuilder}

WithOptions(Func<{DriverOptions}> optionsCreator)

Specifies the driver options factory method.

public {DriverBuilder}

WithOptions(Action<{DriverOptions}> optionsInitializer)

Specifies the driver options initialization method.

public {DriverBuilder}

WithOptions(Dictionary<string, object> optionsPropertiesMap)

Specifies the properties map for the driver options.

public {DriverBuilder}

AddAdditionalOption(string optionName, object optionValue)

Adds the additional option to the driver options.

public {DriverBuilder}

AddAdditionalBrowserOption(string optionName, object optionValue)

Adds the additional browser option to the driver options.

public {DriverBuilder}

WithDriverService(Func<{DriverService}> driverServiceCreator)

Specifies the driver service factory method.

public {DriverBuilder}

WithDriverService(Action<{DriverService}> serviceInitializer)

Specifies the driver service initialization method.

public {DriverBuilder}

WithDriverService(Dictionary<string, object> servicePropertiesMap)

Specifies the properties map for the driver service.

public {DriverBuilder}

WithDriverPath(string driverPath)

Specifies the directory containing the driver executable file.

public {DriverBuilder}

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).

public {DriverBuilder}

WithDriverExecutableFileName(string driverExecutableFileName)

Specifies the name of the driver executable file.

public {DriverBuilder}

WithCommandTimeout(TimeSpan commandTimeout)

Specifies the command timeout (the maximum amount of time to wait for each command). The default timeout is 60 seconds.

public {DriverBuilder}

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.

public {DriverBuilder}

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.

public {DriverBuilder}

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.

public {DriverBuilder}

WithInitialHealthCheckFunction(Func<IWebDriver, bool> function)

Sets the initial health check function. The default function requests IWebDriver.Url.

public {DriverBuilder}

WithPortsToIgnore(params int[] portsToIgnore)

public {DriverBuilder}

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:

public AtataContextBuilder

Add<TLogConsumer>(Action<LogConsumerBuilder<TLogConsumer>>? configure = null)

where TLogConsumer : ILogConsumer, new()
public AtataContextBuilder

Add<TLogConsumer>(TLogConsumer consumer, Action<LogConsumerBuilder<TLogConsumer>>? configure = null)

where TLogConsumer : ILogConsumer

Adds the log consumer.

public AtataContextBuilder

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.

public AtataContextBuilder

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 the LogConsumerNotFoundException if 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.
public AtataContextBuilder

AddTrace(Action<LogConsumerBuilder<TraceLogConsumer>>? configure = null)

Adds the TraceLogConsumer instance that uses System.Diagnostics.Trace class for logging.

public AtataContextBuilder

AddDebug(Action<LogConsumerBuilder<DebugLogConsumer>>? configure = null)

Adds the DebugLogConsumer instance that uses System.Diagnostics.Debug class for logging.

public AtataContextBuilder

AddConsole(Action<LogConsumerBuilder<ConsoleLogConsumer>>? configure = null)

Adds the ConsoleLogConsumer instance that uses System.Console class for logging.

Extension methods from Atata.NUnit library

public AtataContextBuilder

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

public AtataContextBuilder

AddNLog(Action<LogConsumerBuilder<ConsoleLogConsumer>>? configure = null)

Adds the NLogConsumer instance that uses NLog.Logger class for logging.

public AtataContextBuilder

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:

public LogConsumerBuilder<TTLogConsumer>

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.

public LogConsumerBuilder<TTLogConsumer>

WithMinLevel(LogLevel level)

Specifies the minimum level of the log event to write to the log. The default value is Trace.

public LogConsumerBuilder<TTLogConsumer>

WithNestingLevelIndent(string messageNestingLevelIndent)

Sets the nesting level indent. The default value is "- ".

public LogConsumerBuilder<TTLogConsumer>

WithSectionStartPrefix(string sectionStartPrefix)

Sets the prefix of section start. The default value is "> ".

public LogConsumerBuilder<TTLogConsumer>

WithSectionEndPrefix(string sectionEndPrefix)

Sets the prefix of section end. The default value is "< ".

public LogConsumerBuilder<TTLogConsumer>

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.

public LogConsumerBuilder<TTLogConsumer>

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.

public LogConsumerBuilder<TTLogConsumer>

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.

public LogConsumerBuilder<TTLogConsumer>

WithTargetScopes(AtataContextScopes scopes)

Sets the target scopes for which to apply the log consumer. The default value is AtataContextScopes.All.

public LogConsumerBuilder<TTLogConsumer>

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:

public ScreenshotsWebDriverSessionBuilder

UseWebDriverViewportStrategy()

Sets the WebDriver viewport (WebDriverViewportScreenshotStrategy) strategy for a screenshot taking.

public ScreenshotsWebDriverSessionBuilder

UseWebDriverFullPageStrategy()

Sets the WebDriver full-page (WebDriverFullPageScreenshotStrategy) strategy for a screenshot taking. Works only for FirefoxDriver.

public ScreenshotsWebDriverSessionBuilder

UseCdpFullPageStrategy()

Sets the CDP full-page (CdpFullPageScreenshotStrategy) strategy for a screenshot taking. Works only for ChromeDriver and EdgeDriver.

public ScreenshotsWebDriverSessionBuilder

UseFullPageOrViewportStrategy()

Sets the “full-page or viewport” (FullPageOrViewportScreenshotStrategy) strategy for a screenshot taking.

public ScreenshotsWebDriverSessionBuilder

UseStrategy(IScreenshotStrategy strategy)

Sets the strategy for a screenshot taking. The default value is an instance of WebDriverViewportScreenshotStrategy.

public ScreenshotsWebDriverSessionBuilder

UseFileNameTemplate(string fileNameTemplate)

Sets the file name template of page screenshots. The default value is "{screenshot-number:D2}{screenshot-pageobjectname: *}{screenshot-pageobjecttypename: *}{screenshot-title: - *}".

public ScreenshotsWebDriverSessionBuilder

UseFileNameTemplate(string fileNameTemplate)

Sets the file name template of page screenshots. The default value is "{screenshot-pageobjectname}{screenshot-pageobjecttypename:_*}{screenshot-title:-*}".

public ScreenshotsWebDriverSessionBuilder

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:-*}".

public ScreenshotsWebDriverSessionBuilder

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.

public ScreenshotsWebDriverSessionBuilder

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:

public PageSnapshotsWebDriverSessionBuilder

UseCdpOrPageSourceStrategy()

Sets the “CDP or page source” (CdpOrPageSourcePageSnapshotStrategy) strategy for a page snapshot taking.

public PageSnapshotsWebDriverSessionBuilder

UsePageSourceStrategy()

Sets the page source (PageSourcePageSnapshotStrategy) strategy for a page snapshot taking.

public PageSnapshotsWebDriverSessionBuilder

UseCdpStrategy()

Sets the CDP (CdpPageSnapshotStrategy) strategy for a page snapshot taking.

public PageSnapshotsWebDriverSessionBuilder

UseStrategy(IPageSnapshotStrategy strategy)

Sets the strategy for a page snapshot taking. The default value is an instance of CdpOrPageSourcePageSnapshotStrategy.

public PageSnapshotsWebDriverSessionBuilder

UseFileNameTemplate(string fileNameTemplate)

Sets the file name template of page snapshots. The default value is "{snapshot-pageobjectname}{snapshot-pageobjecttypename:_*}{snapshot-title:-*}".

public PageSnapshotsWebDriverSessionBuilder

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:-*}".

public PageSnapshotsWebDriverSessionBuilder

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.

public PageSnapshotsWebDriverSessionBuilder

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:

  • AtataContextPreInitEvent
  • AtataContextInitStartedEvent
  • AtataContextInitCompletedEvent
  • AtataContextDeInitStartedEvent
  • AtataContextDeInitCompletedEvent
  • AtataSessionAssignedToContextEvent
  • AtataSessionUnassignedFromContextEvent
  • AtataSessionInitStartedEvent
  • AtataSessionInitCompletedEvent
  • AtataSessionDeInitStartedEvent
  • AtataSessionDeInitCompletedEvent
  • ArtifactAddedEvent
  • PageObjectInitStartedEvent
  • PageObjectTransitionInCompletedEvent
  • PageObjectTransitionOutCompletedEvent
  • PageObjectInitCompletedEvent
  • PageObjectDeInitCompletedEvent
  • WebDriverInitCompletedEvent
  • WebDriverDeInitStartedEvent

Find more details on events and subscriptions on the Events page.

The list of methods of EventSubscriptionsBuilder<TRootBuilder>:

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>(IEventHandler<TEvent> eventHandler)

public TRootBuilder

Add<TEvent>(IAsyncEventHandler<TEvent> eventHandler)

Adds the specified event handler as a subscription to the TEvent.

public TRootBuilder

Add<TEvent, TEventHandler>()

where TEventHandler : class, IEventHandler<TEvent>, new()

Adds the created instance of TEventHandler as a subscription to the TEvent.

public TRootBuilder

Add<TEvent>(Type eventType, Type eventHandlerType)

Adds the created instance of eventHandlerType as a subscription to the eventType.

public TRootBuilder

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.

public TRootBuilder

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.

public TRootBuilder

AddArtifactsToNUnitTestContext()

Defines that after AtataContext deinitialization the files stored in Artifacts directory should be added to NUnit TestContext.

public TRootBuilder

AddDirectoryFilesToNUnitTestContext(string directoryPath)

public TRootBuilder

AddDirectoryFilesToNUnitTestContext(Func<string> directoryPathBuilder)

public TRootBuilder

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.

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

public static T

To<T>(T pageObject = null, string url = null, bool navigate = true, bool temporarily = false)

where T : PageObject<T>

Navigates to the specified page object.

public static T

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.

public static T

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.

public static T

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.

public static T

ToWindow<T>(T pageObject, string windowName, bool temporarily = false)

where T : PageObject<T>

Navigates to the window with the specified page object by name.

public static T

ToWindow<T>(string windowName, bool temporarily = false)

where T : PageObject<T>

Navigates to the window by name.

public static T

ToNextWindow<T>(T pageObject = null, bool temporarily = false)

where T : PageObject<T>

Navigates to the next window with the specified page object.

public static T

ToPreviousWindow<T>(T pageObject = null, bool temporarily = false)

where T : PageObject<T>

Navigates to the previous window with the specified page object.

public static void

ToUrl(string url)

Navigates to the specified URL.

public static T

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.

public static T

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 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

public TOwner

Trace(string message)

Writes a trace log message.

public TOwner

Debug(string message)

Writes a debug log message.

public TOwner

Info(string message)

Writes an informational log message.

public TOwner

Warn(Exception exception)

public TOwner

Warn(string message)

public TOwner

Warn(Exception exception, string message)

Writes a warning log message.

public TOwner

Error(Exception exception)

public TOwner

Error(string message)

public TOwner

Error(Exception exception, string message)

Writes an error log message.

public TOwner

Fatal(Exception exception)

public TOwner

Fatal(string message)

public TOwner

Fatal(Exception exception, string message)

Writes a critical log message.

public TOwner

Setup(string message, Action<TOwner> action)

public TOwner

Setup<TResult>(string message, Func<TOwner, TResult> function)

public Task

SetupAsync(string message, Func<TOwner, Task> action)

public Task<TResult>

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.

public TOwner

Step(string message, Action<TOwner> action)

public TOwner

Step<TResult>(string message, Func<TOwner, TResult> function)

public Task

StepAsync(string message, Func<TOwner, Task> action)

public Task<TResult>

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

public TOwner

Screenshot(string title = null)

Takes a screenshot of the current page with an optionally specified title.

public TOwner

Screenshot(ScreenshotKind kind, string title = null)

Takes a screenshot of the current page of a certain kind with an optionally specified title.

public TOwner

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

public TOwner

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.

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)]

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<_>
{
}

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.

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");

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 through EventSubscriptions property of AtataContextBuilder.
  • AtataSessionEventSubscriptionsBuilder<TSessionBuilder>- available through EventSubscriptions property of AtataSessionBuilder<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 before AtataContext initialization.
  • AtataContextInitStartedEvent - occurs when AtataContext is started to initialize.
  • AtataContextInitCompletedEvent - occurs when AtataContext is initialized.
  • AtataContextDeInitStartedEvent - occurs when AtataContext is started to deinitialize.
  • AtataContextDeInitCompletedEvent - occurs when AtataContext is deinitialized.

AtataSession events

  • AtataSessionAssignedToContextEvent - occurs when AtataSession is assigned to AtataContext.
  • AtataSessionUnassignedFromContextEvent - occurs when AtataSession is unassigned from AtataContext.
  • AtataSessionInitStartedEvent - occurs when AtataSession is started to initialize.
  • AtataSessionInitCompletedEvent - occurs when AtataSession is initialized.
  • AtataSessionDeInitStartedEvent - occurs when AtataSession is started to deinitialize.
  • AtataSessionDeInitCompletedEvent - occurs when AtataSession is deinitialized.

Artifact events

  • ArtifactAddedEvent - occurs when an artifact file is saved.

PageObject events

  • PageObjectInitStartedEvent - occurs when PageObject<TOwner> is started to initialize.
  • PageObjectTransitionInCompletedEvent - occurs when PageObject<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 when PageObject<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 when PageObject<TOwner> is initialized.
  • PageObjectDeInitCompletedEvent - occurs when PageObject<TOwner> is deinitialized.

WebDriver events

  • WebDriverInitCompletedEvent - occurs when WebDriverSession.Driver is initialized.
  • WebDriverDeInitStartedEvent - occurs when WebDriverSession.Driver is started to deinitialize.