What's coming to Atata 4

April 16, 2025 by Yevgeniy Shunevych


Introducing upcoming Atata 4 key features and improvements.

The primary change involves a significant update to AtataContext, redefining its concept and configuration by introducing the new WebDriverSession and the concept of sessions, which are now separated from AtataContext.

AtataContext

Since v4, AtataContext can be bound to the current test, test suite, fixture, namespace, or global scope.

It is possible to have a hierarchy of AtataContext instances. The ParentContext and ChildContexts properties have been added to AtataContext for hierarchical navigation. The AtataContext.Global static property represents the root of the hierarchy.

All WebDriver functionality is moving out of AtataContext. For backward compatibility and smoother migration, the old AtataContext properties (like Driver) and methods (like TakeScreenshot) remain marked as obsolete and will be removed in v5. The Atata v5 library itself will be stripped of WebDriver functionality, which will be extracted into a separate package, likely named Atata.WebDriver. With v5, Atata will evolve into a universal framework, no longer tightly coupled with WebDriver/UI testing. Additional modules, such as those for HTTP/REST testing, are planned for future releases.

Integration with test frameworks

There will be separate NuGet packages to simplify integration of Atata with test frameworks: Atata.NUnit, Atata.Xunit, Atata.XUnit3, Atata.MSTest, and Atata.Reqnroll.NUnit. These libraries provide base classes like AtataTestSuite and AtataGlobalFixture. However, these libraries are optional, and you can configure and use AtataContext as needed.

Sessions

The functionality related to WebDriver has been extracted into WebDriverSession, WebDriverSessionBuilder, and other related classes. It is currently still part of the Atata library.

AtataSession is a new concept. WebDriverSession is the first implementation of AtataSession. Each AtataContext can have any number of sessions it needs, either starting them up during context build or later during execution. Configure them as needed. 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.

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.

State

public StateHierarchicalDictionary State { get; } property has been added to 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>();

Page objects

There were no major changes related to UI components. There might be some minor changes, but breaking changes are not expected in this part.

Configuration

The configuration was reworked and changed significantly. Below is an example of AtataContext configuration in a global fixture:

[SetUpFixture]
public class GlobalFixture : AtataGlobalFixture
{
    protected override void ConfigureAtataContextGlobalProperties(AtataContextGlobalProperties globalProperties) =>
        globalProperties.UseRootNamespaceOf<GlobalFixture>();

    protected override void ConfigureAtataContextBaseConfiguration(AtataContextBuilder builder) =>
        builder
            .UseCulture("en-US")
            .Sessions.AddWebDriver(x => x
                .UseStartScopes(AtataContextScopes.Test)
                .UseBaseUrl("https://demo.atata.io/")
                .UseChrome(x => x
                    .WithArguments("headless=new", "window-size=1024,768", "disable-search-engine-choice-screen")))
            .LogConsumers.AddNLogFile();

    protected override void ConfigureGlobalAtataContext(AtataContextBuilder builder) =>
        builder.EventSubscriptions.Add(SetUpWebDriversForUseEventHandler.Instance);
}

JSON configuration

Atata.Configuration.Json package will not be upgraded to v4 and will continue to support only Atata v3. The Atata JSON configuration will be deprecated. With all the new Atata changes and modularity, it is challenging to maintain JSON configuration compatibility. I hope this will not pose a significant issue for most users. JSON configuration can be migrated to the built-in runtime configuration with the help of Microsoft.Extensions.Configuration, using environment variables, test parameters, or custom configuration files. A documentation page with an example of the JSON configuration migration process will be provided.

Artifacts

There was an improvement of AtataContext Artifacts relative path. Staring v4, namespace of test suite class also participates in the Artifacts path. There was a problem in v3, when you had test suite classes with the same name under different namespaces, their results were merged into the same test suite directory.

For example, if you have a test Test1 in a suite class SomeProject.UITests.SomeFeature.SomeTests of SomeProject.UITests project, here is what the relative Artifacts path will be:

v3: /SomeTests/Test1
v4: /SomeFeature/SomeTests/Test1

Artifacts structure

Here is how the Artifacts file structure looks in v4 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)

Logging

Logging was also reworked. The default timestamp format has been changed. Session ID is written by default to the log between timestamp and log level. Category and external source properties have been added to log entry.

Log timestamp

v3: 2025-04-16 12:34:06.466 - the current local timestamp
v4: 00:00:00.001 - the time elapsed since the start of the corresponding AtataContext.

Category

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.

External source

Use ForExternalSource method of ILogManager to log messages with a specific external source.

Context.Log.ForExternalSource("Some source").Debug("Some message");

->

00:00:00.001 hDrP DEBUG <Some source> Some message

For example, browser logs are now reported with “Browser” external source:

v3:

2025-04-16 12:34:06.466 TRACE - Browser log: 12:34:06.375 DEBUG http://localhost:50549/browserlogs 14:12 "console debug log entry"
2025-04-16 12:34:06.468 TRACE - Browser log: 12:34:06.376 ERROR http://localhost:50549/browserlogs 17:12 "console error log entry"

v4:

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.

NLog

NLog-related functionality is extracted from Atata package to a separate Atata.NLog package.

ExtentReports

Integration with ExtentReports is now streamlined via the new Atata.ExtentReports package. Previously, you needed to follow the Reporting to ExtentReports tutorial. With v4 you will be able to configure ExtentReports with a single UseExtentReports() method call on the base AtataContextBuilder.

C# nullable reference types

Starting with v4, Atata is fully compatible with C# nullable reference types.

Misc

All types and members marked as obsolete before v4 have been removed, as is customary with major Atata releases. Before upgrading, ensure all obsolete Atata warnings in your code are resolved.

Release date

Beta version of Atata 4 is expected to be released in May 2025. The final release is planned for summer 2025.

P.S.

Any feedback is welcome. Contact me, if you have any questions or suggestions.