Table of Contents

Console Application Guide

This tutorial demonstrates how to create a .NET console application that utilizes the Xping SDK library. You will start by creating a basic test agent and adding a reporting service. Then, you will build upon that foundation by creating a validation pipeline that contains multiple test steps which will run test operations to validate server response.

Check out the samples folder on our GitHub repository to discover more amazing examples and learn how they can benefit you.

Prerequisites

Or

Create the app

  • Create a .NET 8 console app project named "ConsoleApp".

  • Create a folder named ConsoleApp for the project, and then open a command prompt in the new folder.

Run the following command:

dotnet new console --framework net8.0

Install the Xping.Sdk package

Run the following command:

dotnet add package Xping.Sdk --prerelease

The --prerelease option is necessary because the library is still in beta.

Additionally install CommandLine package which we will use in our ConsoleApp to parse and handle command line arguments.

dotnet add package System.CommandLine --prerelease

For more information on how to use CommandLine please follow Command Line Tutorial

Replace the content of the Program.cs with the following code

class Program : XpingAssertions
{
    const int EXIT_SUCCESS = 0;
    const int EXIT_FAILURE = 1;

    const int MAX_SIZE_IN_BYTES = 153600; // 150kB

    static async Task<int> Main(string[] args)
    {
        IHost host = CreateHostBuilder(args).Build();

        var urlOption = new Option<Uri?>(
            name: "--url",
            description: "A URL address of the page being validated.")
        { IsRequired = true };

        var command = new RootCommand("Sample application for Xping SDK");
        command.AddOption(urlOption);
        command.SetHandler(async (InvocationContext context) =>
        {
            Uri url = context.ParseResult.GetValueForOption(urlOption)!;
            var testAgent = host.Services.GetRequiredService<TestAgent>();

            testAgent
                .UseDnsLookup()
                .UseIPAddressAccessibilityCheck()
                .UseHttpClient()
                .UseHttpValidation(response =>
                {
                    Expect(response)
                        .ToHaveSuccessStatusCode()
                        .ToHaveHttpHeader(HeaderNames.Server)
                            .WithValue("Google", new() { Exact = false });
                })
                .UseHtmlValidation(html =>
                {
                    html.HasMaxDocumentSize(MAX_SIZE_IN_BYTES);
                });

            await using var session = await testAgent.RunAsync(url);

            context.Console.WriteLine("\nSummary:");
            context.Console.WriteLine($"{session}");
            context.ExitCode = session.IsValid ? EXIT_SUCCESS : EXIT_FAILURE;
        });

        return await command.InvokeAsync(args);
    }

    static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((services) =>
            {
                services.AddSingleton<IProgress<TestStep>, Progress>()
                        .AddHttpClientFactory()
                        .AddTestAgent(agent =>
                        {
                            agent.UploadToken = "--- Your Dashboard Upload Token ---"; // optional
                        });
            })
            .ConfigureLogging(logging =>
            {
                logging.AddFilter(typeof(HttpClient).FullName, LogLevel.Warning);
            });
}

Add reporting mechanism

Create a new class Progress.cs and replace its content with following:

public sealed class Progress(ILogger<Program> logger) : IProgress<TestStep>
{
    private static readonly Action<ILogger, string, Exception?> LogSuccessMessage = LoggerMessage.Define<string>(
        logLevel: LogLevel.Information, eventId: 1, formatString: "{Value}");
    private static readonly Action<ILogger, string, Exception?> LogErrorMessage = LoggerMessage.Define<string>(
        logLevel: LogLevel.Error, eventId: 2, formatString: "{Value}");

    private readonly ILogger<Program> _logger = logger;

    public void Report(TestStep value)
    {
        ArgumentNullException.ThrowIfNull(value, nameof(value));

        switch (value.Result)
        {
            case TestStepResult.Succeeded:
                LogSuccessMessage(_logger, value.ToString(), null);
                break;
            case TestStepResult.Failed:
                LogErrorMessage(_logger, value.ToString(), null);
                break;
        }
    }
}

The IProgress<TestStep> interface is implemented by this class, which is called on every test step performed by TestAgent during its testing operation. This allows to monitor the progress of the test execution.

The preceding code we added earlier in Program.cs does following:

  • Creates a host with preconfigured defaults, and then adds the Progress class and IHttpClientFactory to the service collection.
Note

To test with a headless browser, consider using services.AddBrowserClientFactory() instead.

static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureServices((services) =>
        {
            services.AddSingleton<IProgress<TestStep>, Progress>()
                    .AddHttpClientFactory()
            (...)
        })
Note

For more information on how to use dependency injection in .NET please follow this Dependency Injection Tutorial.

  • Adds a TestAgent service to the service collection.
services.AddTestAgent(agent =>
{
    agent.UploadToken = "--- Your Dashboard Upload Token ---"; // optional
});
  • Creates an option named --url of type Uri and assigns it to the root command:
var urlOption = new Option<Uri?>(
    name: "--url",
    description: "A URL address of the page being validated.")
{ IsRequired = true };

var command = new RootCommand("Sample application for Xping SDK");
command.AddOption(urlOption);
  • Specifies the handler method that will be called when the root command is invoked and parses the url option:
command.SetHandler(async (InvocationContext context) =>
{
    Uri url = context.ParseResult.GetValueForOption(urlOption)!;
    
    (...)
});

return await command.InvokeAsync(args);
  • The handler method retrieves the TestAgent service, configures its testing pipeline, and runs test operations with default test settings against the url value:

command.SetHandler(async (InvocationContext context) =>
{
    (...)

    var testAgent = host.Services.GetRequiredService<TestAgent>();

    testAgent
        .UseDnsLookup()
        .UseIPAddressAccessibilityCheck()
        .UseHttpClient()
        .UseHttpValidation(response =>
        {
            Expect(response)
                .ToHaveSuccessStatusCode()
                .ToHaveHttpHeader(HeaderNames.Server)
                    .WithValue("Google", new() { Exact = false });
        })
        .UseHtmlValidation(html =>
        {
            html.HasMaxDocumentSize(MAX_SIZE_IN_BYTES);
        });

    await using var session = await testAgent.RunAsync(url);
});
  • Prints out summary and specifies exit code depending on the test results:
command.SetHandler(async (InvocationContext context) =>
{
    (...)

    context.Console.WriteLine("\nSummary:");
    context.Console.WriteLine($"{session}");
    context.ExitCode = session.IsValid ? EXIT_SUCCESS : EXIT_FAILURE;
});

return await command.InvokeAsync(args);

Test the app

Run the dotnet build command, and then open a command prompt in the ConsoleApp/bin/Debug/net8.0 folder to run the executable:

dotnet build
cd bin/Debug/net8.0
ConsoleApp --url https://demoblaze.com

Upon running the application, it performs availability tests on the URL specified by the --url option and prints the results:

ConsoleApp.exe --url http://demoblaze.com

info: ConsoleAppTesting.Program[1]
      9/22/2024 9:11:04 PM (29 ms) [ActionStep]: DNS lookup succeeded.
info: ConsoleAppTesting.Program[1]
      9/22/2024 9:11:04 PM (18 ms) [ActionStep]: IPAddress accessibility check succeeded.
info: ConsoleAppTesting.Program[1]
      9/22/2024 9:11:04 PM (343 ms) [ActionStep]: HttpClientRequestSender succeeded.
info: ConsoleAppTesting.Program[1]
      9/22/2024 9:11:04 PM (4 ms) [ValidateStep]: HttpResponseValidator:EnsureSuccessStatusCode succeeded.
info: ConsoleAppTesting.Program[1]
      9/22/2024 9:11:04 PM (2 ms) [ValidateStep]: HttpResponseValidator:HttpHeader succeeded.
info: ConsoleAppTesting.Program[1]
      9/22/2024 9:11:04 PM (70 ms) [ValidateStep]: HtmlContentValidator:HasMaxDocumentSize succeeded.

Summary:
9/22/2024 9:11:04 PM (465 ms) Test session completed for https://demoblaze.com/.
Total steps: 6, Success: 6, Failures: 0

Congratulations! You have successfully completed this tutorial on how to use the Xping SDK. You have learned how to create a .NET console application that utilizes the Xping SDK library to automate web application testing. You have also learned how to create a basic test agent, add a reporting service, and build a validation pipeline that contains multiple test components.

For a complete implementation of this tutorial, please refer to our sample folder.