Capturing API traffic during your end-to-end testing using Selenium
Have you ever been interested in tracking which endpoints your functional or end-to-end tests hit during execution? Using Selenium's Chrome Dev Tools (CDT) network interface is a simple way to implement a listener that can record and filter network events.
Let's implement this interceptor during a simple feature test. In this example, I am using ReqnRoll 2.2 and Selenium 4.26
Testery.feature:
Feature: Testery
@homepage
Scenario: Visit Testery Site
Given I navigate to testery.com
Then I see the testery links
When I click on contact link
Then I see the contact page
We have the normal step files set up to go through the actions. All that is needed to start monitoring network traffic is to set up a new BeforeScenario step modify the clean-up step to stop the interceptor and save the captured data to a file.
Hooks.cs (before)
using OpenQA.Selenium.Chrome;
namespace ReqnrollProject1.StepDefinitions
{
[Binding]
public class Hooks
{
public IWebDriver Driver { get; private set; } = null!;
[BeforeScenario]
public async Task SetupTest()
{
ChromeOptions options = new()
{
BrowserVersion = "stable",
};
options.AddArguments("--window-size=1920,1080");
Driver = new ChromeDriver(options);
}
[AfterScenario]
public async Task TearDown()
{
Driver.Quit();
}
}
}
Hooks.cs (after):
using OpenQA.Selenium.Chrome;
using System.Text.Json;
namespace ReqnrollProject1.StepDefinitions
{
[Binding]
public class Hooks(ScenarioContext scenarioContext)
{
public IWebDriver Driver { get; private set; } = null!;
public INetwork networkInterceptor;
public List<string> Urls = [];
[BeforeScenario(Order = 0)]
public async Task SetupTest()
{
ChromeOptions options = new()
{
BrowserVersion = "stable",
};
options.AddArguments("--window-size=1920,1080");
Driver = new ChromeDriver(options);
string path = @".\Output";
if (Directory.Exists(path))
{
DirectoryInfo di = new(path);
foreach (FileInfo file in di.GetFiles())
{
file.Delete();
}
}
Directory.CreateDirectory(path);
}
[BeforeScenario(Order = 1)]
public async Task ResponseListener()
{
networkInterceptor = Driver.Manage().Network;
networkInterceptor.NetworkResponseReceived += (_, e) =>
{
string url = e.ResponseUrl;
if (url.Contains("testery.com/"))
{
Urls.Add(url);
}
};
await networkInterceptor.StartMonitoring();
}
[AfterScenario]
public async Task TearDown()
{
await networkInterceptor.StopMonitoring();
Driver.Quit();
string fileName = scenarioContext.ScenarioInfo.Title.Replace(" ", "_");
await using FileStream createStream = File.Create($@".\Output\{fileName}_urls.json");
await JsonSerializer.SerializeAsync(createStream, Urls);
}
}
}
The modified file now includes a directory set up for our recorded data and will create files using the scenario name to keep separate logs for each test.
A new step will initialize and start the network interceptor and filter addresses we are interested in (after the driver has been created).
Finally, the TearDown step will end the processes, and the results will be written as a JSON.
For each test, you'll receive a file under "Output" in your bin with a JSON of all the network response URLs.
[
"https://www.testery.com/",
"https://testery.com/",
"https://testery.com/images/testRunResultsFast.png",
"https://testery.com/images/testery-black-wide-logo.png",
"https://testery.com/images/testery_wide_white.png",
]
Now you can customize the filters or add a listener for requests as well.
For more information, please check out the official Selenium docs.
Happy Testing!