Wednesday, April 2, 2025

The following code demonstrates how to update your .NET 6 application to use the new IHostBuilder interface in .NET 8. It also shows how to run Playwright tests using NUnit with either a headless or headed browser, regardless of the operating system: “`csharp using Microsoft.Extensions.Hosting; using NUnit.Framework; using PlaywrightSharp; namespace Tests { [TestFixture] public class MyTest : IHostedFixture { private readonly IHost _host; public MyTest(IHost host) { _host = host; } [OneTimeSetUp] public void OneTimeSetup() { _host.Start(); } [OneTimeTearDown] public void OneTimeTeardown() { _host.Stop(); } [Test, Headless] public async Task MyHeadlessTest() { using var playwright = await Playwright.Run(); // Your test code here } [Test, NotHeadless] public async Task MyHeadedTest() { using var playwright = await Playwright.Run(headless: false); // Your test code here } } } “`

All the Unit Tests passSince the early days of 2007, I’ve consistently pushed beyond basic unit testing to implement comprehensive integration testing and browser automation testing utilizing Selenium’s capabilities. Despite recent developments, I’ve been leveraging faster and more suitable methods. The application has a single API that can be executed on various platforms, including Windows, Linux, and Mac, as well as locally within a container, through the continuous integration and delivery (CI/CD) pipeline on Azure DevOps or within GitHub Actions?

To guarantee a seamless experience, I make sure that the playback positioning starts smoothly and consistently from start to end.

I can write these Playwright tests in one thing like TypeScript, and I might launch them with Node; however, I prefer running end-to-end unit tests using that test runner and test harness as my starting point for my .NET projects. As a developer accustomed to precise clicks, I’m well-versed in navigating Visual Studio or VS Code by properly clicking “Run Unit Tests” and elevating it further with a click on “Debug Unit Tests”. By integrating this approach with a comprehensive unit testing framework, I can leverage the collective benefits of both, including robust assertion capabilities and the efficiency of automating browser interactions via Playwright.

Here is the rewritten text:

Within a few swift iterations, you can successfully bootstraps ASP.NET within the confines of .NET Core 2.1, followed by executing Selenium-based tests during the unit test suite. This form of data was unstructured and would necessitate manual processing to initiate a separate instance of the course and manage its entire lifecycle. Despite initial challenges, I successfully utilized this workaround for several years while primarily striving to successfully launch the Kestrel Net Server during my unit tests.

I’ve recently upgraded my crucial websites, including both my main site and podcast platform, to the latest version of .NET 8. As I’ve progressed my websites forward, I’ve upgraded them from early iterations of .NET to the most recent versions. Fortunately, the blog operates within a Linux container on .NET 8, although its legacy codebase dates back to 2002 when it was initially developed for .NET 1.1.

Now that I’ve upgraded to .NET 8, I’m astonished to discover that my unit tests have ceased functioning properly. Gulp. Say what you will, though, the backward compatibility is truly spectacular?

As such my code for Program.cs modified from this

public static void Primary(string[] args)
{
CreateWebHostBuilder(args).Construct().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();

to this:

public static void Primary(string[] args)
{
CreateHostBuilder(args).Construct().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args).
ConfigureWebHostDefaults(WebHostBuilder => WebHostBuilder.UseStartup<Startup>());

Notwithstanding its seemingly trivial nature, this subtle shift actually has a profound impact on the inner workings of the system, effectively aligning it.

My units’ checks ceased functioning after I implemented the Kestrel Net Server hack, preventing my server from booting up successfully?

The browser is launched from within a .NET NUnit test using the Playwright framework, which enables automated testing of web applications.

[Test]
public async Process DoesSearchWork()
{
await Web page.GotoAsync(Url);

Webpage.Locator("#topbar").Find(AriaRole.Hyperlink, "episodes").Click();

await Web page.GetByPlaceholder("search and filter").ClickAsync();

await Web page.GetByPlaceholder("search and filter").TypeAsync("spouse");

const string visibleCards = ".showCard:seen";

var ready = await _webpage.WaitForSelectorAsync(virtualCards, new PageWaitForSelectorOptions { Timeout = TimeSpan.FromMilliseconds(500) });

await Anticipate(Web page.Locator(visibleCards).First).ToBeVisibleAsync();

await Anticipate(Web page.Locator(visibleCards)).ToHaveCountAsync(5);
}

I really like this. Good and clear. We’re assuming that we have a URL in the initial statement, likely a local host instance, followed by the assumption that our internet software has launched automatically.

The following code sets up my new internet-based software testing factory, a name that may be silly but is straightforwardly descriptive. This setup and teardown functionality seems intriguing; what’s its purpose in this context? The application launches within the scope of my test host environment. Upon identifying the assigned port :0, the application automatically detects it, subsequently requiring me to meticulously locate and integrate the designated port number within the URL, thereby ensuring seamless utilization throughout my unit exams. Notice that the <Startup> is in reality my Startup class inside Startup.cs which hosts my app’s pipeline and Configure and ConfigureServices get setup right here so routing all works.

personal string Url;
personal WebApplication? _app = null;

[OneTimeSetUp]
public void Setup()
{
var builder = WebApplicationTestBuilderFactory.CreateBuilder<Startup>();

var startup = new Startup(builder.Setting);
builder.WebHost.ConfigureKestrel(o => o.Pay attention(IPAddress.Loopback, 0));
startup.ConfigureServices(builder.Companies);
_app = builder.Construct();

Hear on any native port, specifically including port 0.
startup.Configure(_app, _app.Configuration);
_app.Begin();

//you might be kidding me
Url = _app.Companies.GetRequiredService<IServer>().Options.GetRequiredFeature<IServerAddressesFeature>().Addresses.Final();
}

[OneTimeTearDown]
public async Process TearDown()
{
await _app.DisposeAsync();
}

What dark secrets lurk beneath the surface of this mysterious class, waiting to unleash their chaos upon unsuspecting developers who dare to venture too close? The very thought sends shivers down one’s spine – it’s a veritable graveyard of despair where tests go to die, forever trapped in an abyss of infinite recursion and mocking null pointer exceptions. The primary bit is indeed problematic and requires immediate attention to ensure seamless compatibility with the latest .NET 9 framework. The remaining is undoubtedly excellent, with a nod of appreciation to David Fowler for his invaluable assistance and guidance. The essence of both magic and complexity lies within this concise, yet powerful, helper class.

public class WebApplicationTestBuilderFactory 
{
public static WebApplicationBuilder CreateBuilder<T>() the place T : class
{
Why does this ancient code insist on referencing the MvcTesting bundle, begging the question of its relevance and utility?
Using MSBuild to generate a manifest file requires a basic understanding of how this process works.
var testLocation = Path.Mix(AppContext.BaseDirectory, "MvcTestingAppManifest.json");
var json = JsonObject.Parse(File.ReadAllText(testLocation));
var asmFullName = typeof(T).Meeting.FullName ?? throw new InvalidOperationException("The MeetingFullIdentity property cannot be null.");
var contentRootPath = json?[asmFullName]?.GetValue<string>();

Spin up a fully-fledged internet software within the confines of TestHost.exe.
var builder = WebApplication.CreateBuilder(
new WebApplicationOptions()
{
ContentRootPath = contentRootPath,
ApplicationName = asmFullName
});
return builder;
}
}

The four primary influenza strains are indeed highly problematic. As part of a special listing’s review runs on my website, I need to ensure that the content material root path is accurate and aligned with its own context. To achieve this, I must obtain the apps base directory from an MSBuild-generated file within the aging MvcTesting package. Although the bundle remains unused initially, referencing it enables its integration into the construct, ultimately allowing me to generate the file that facilitates extracting the list.

If we successfully eliminate that hack, allowing the listing to be pulled from context elsewhere, the helper function can be reduced to a single line, significantly increasing its testability under .NET 9.

Now I can execute unit exams and playwright browser integration exams seamlessly across all operating systems, whether headed or headless, within Docker containers or running natively on metal. The project has been updated to utilize the latest features of .NET 8, and I am confident that my modifications are accurate. It nicely does run, doesn’t it? 😉

About Scott

Scott Hanselman, a multifaceted individual, is a former professor who has transitioned to become a renowned speaker, devoted father, and advocate for those living with diabetes, in addition to his roles as Chief Architect in the finance sector and Microsoft employee. He’s a former stand-up comedian whose career didn’t quite take off, also skilled in the art of cornrowing hair, and has successfully transitioned to writing digital books.

 

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles