AI presents both a once-in-a-generation opportunity and a challenge to help every employee conquer the infinite workday.
The post How Microsoft 365 Copilot and agents help tackle the infinite workday appeared first on Microsoft 365 Blog.
AI presents both a once-in-a-generation opportunity and a challenge to help every employee conquer the infinite workday.
The post How Microsoft 365 Copilot and agents help tackle the infinite workday appeared first on Microsoft 365 Blog.
basePath
property in config objectsConfig objects can now include the new basePath
property to specify the path to a subdirectory to which the config object should apply to. If a config object has a basePath
property, patterns specified in files
and ignores
are evaluated relative to the subdirectory represented by basePath
. This makes it easier to write config objects that target a particular directory inside your project.
// eslint.config.js
import { defineConfig } from "eslint/config";
import js from "@eslint/js";
export default defineConfig([
{
basePath: "packages/hello-base-path",
plugins: { js },
extends: ["js/recommended"],
ignores: ["coverage/**", "dist/**"],
},
]);
You can read more about base paths in config objects in the documentation
.
v10_config_lookup_from_file
With the addition of the basePath
property in config objects, the experimental configuration file resolution introduced in ESLint v9.12.0 has been finalized. It will become the default behavior in the next major release of ESLint. Accordingly, the feature flag unstable_config_lookup_from_file
has been renamed to v10_config_lookup_from_file
. The old flag name still works, so if you are already using unstable_config_lookup_from_file
in your setup, you don’t need to take any action.
allowSeparateTypeImports
option in no-duplicate-imports
With the new option allowSeparateTypeImports
, the no-duplicate-imports
rule can now be configured to treat import
and import type
as separate usages, even if they specify the same module.
/*eslint no-duplicate-imports: ["error", { "allowSeparateTypeImports": false }]*/
import { someValue } from 'module';
import type { SomeType } from 'module';
SourceCode
method getIndexFromLoc
now throws an error if the argument specifies a negative value for the column
property.52a5fca
feat: Support basePath
property in config objects (#19879) (Milos Djermanovic)4ab4482
feat: add allowSeparateTypeImports
option to no-duplicate-imports
(#19872) (sethamus)b8a7e7a
feat: throw error when column is negative in getIndexFromLoc
(#19831) (루밀LuMir)6a0f164
fix: handle null
type loc
in getIndexFromLoc
method (#19862) (루밀LuMir)3fbcd70
fix: update error message for no-restricted-properties
(#19855) (Tanuj Kanti)7ef4cf7
fix: remove unnecessary semicolon from fixes (#19857) (Francesco Trotta)7dabc38
fix: use process.version
in --env-info
(#19865) (TKDev7)8662ed1
docs: adopt eslint-stylistic sub packages related changes (#19887) (ntnyq)20158b0
docs: typo in comment for unused variables handling (#19870) (leopardracer)ebfb5b4
docs: Fixed Typo in configuration-files.md (#19873) (0-20)4112fd0
docs: clarify that boolean is still allowed for rule meta.deprecated
(#19866) (Bryan Mishkin)Our old friend Chris McCord, creator of Elixir’s Phoenix framework, tells us all about his new remote AI runtime for building Phoenix apps. Along the way, we vibe code one of my silly app ideas, calculate all the money we’re going to spend on these tools, and get existential about what it all means.
Changelog++ members save 4 minutes on this episode because they made the ads disappear. Join today!
Sponsors:
Featuring:
Show Notes:
Something missing or broken? PRs welcome!
In this episode, Andy welcomes back leadership coach Josefine Campbell to discuss her newest book, 12 Tools for Managing a Selfish Leader. If you’ve ever had a boss who seemed unpredictable, emotionally draining, or even manipulative, this conversation offers tools and insights that can help.
Josefine shares the inspiration behind the book, which is based on the story of a coaching client who successfully navigated a toxic leadership environment. You’ll learn how to identify the early signals of stress in yourself and your team, apply tools like the Stress Staircase and the Three Relationship Circles, and recognize behaviors like “praise with a twist.” Most importantly, Josefine emphasizes the critical turning point: recognizing that while you can’t change a selfish leader, you can change how you manage yourself to better navigate the relationship.
If you’re looking for insights on how to manage up, preserve your well-being, and lead yourself through challenging leadership dynamics, this episode is for you!
You can learn more about Josefine and her book at josefinecampbell.com/books.
For more learning on this topic, check out:
If you or someone you know is thinking about getting PMP certified, we’ve put together a helpful guide called The 5 Best Resources to Help You Pass the PMP Exam on Your First Try. We’ve helped thousands of people earn their certification, and we’d love to help you too. It's totally free, and it's a great way to get a head start.
Just go to 5BestResources.PeopleAndProjectsPodcast.com to grab your copy. I’d love to help you get your PMP this year!
Thank you for joining me for this episode of The People and Projects Podcast!
Talent Triangle: Power Skills
Topics: Leadership, Project Management, Managing Up, Emotional Intelligence, Coaching, Stress Management, Toxic Leadership, Conflict Navigation, Workplace Psychology, Self-Leadership, Empathy, Team Dynamics
The following music was used for this episode:
Music: Summer Awakening by Frank Schroeter
License (CC BY 4.0): https://filmmusic.io/standard-license
Music: Tuesday by Sascha Ende
License (CC BY 4.0): https://filmmusic.io/standard-license
BREAKING: PagerDuty Actually Fixed Incident Management
Remember when PagerDuty was just for alerting?
Plot twist: They've quietly bundled and enhanced complete incident management into ALL plans -
including custom workflows, Slack-first everything, AI-powered summaries, and incident roles.
Your incident management deserves better than browser tabs and hope.
Check it out here.
Nick Chapsas' Dometrain is celebrating 2 years of teaching .NET developers, and they are offering their "From Zero to Hero: REST APIs in .NET" course for free. Until the end of June, use the link below, and the course is yours to keep for 1 month. Get it for free.
Integration tests with Testcontainers are powerful, but they can quickly become a maintenance nightmare if you don't follow the right patterns.
I've seen teams struggle with flaky tests, slow test suites, and configuration headaches that could have been avoided with better practices from the start.
Today, I'll show you the patterns that make Testcontainers tests reliable, fast, and easy to maintain.
Traditional integration tests often rely on shared test databases or in-memory alternatives that don't match production behavior. You either deal with test pollution between runs or sacrifice realism for speed.
Testcontainers solves this by spinning up real Docker containers for your dependencies. Your tests run against actual PostgreSQL, Redis, or any other service you use in production. When tests complete, containers are destroyed, giving you a clean slate every time.
The magic happens through Docker's API. Testcontainers manages the entire lifecycle: pulling images, starting containers, waiting for readiness, and cleanup. Your test code just needs to know how to connect.
First, make sure you have the necessary packages:
Install-Package Microsoft.AspNetCore.Mvc.Testing
Install-Package Testcontainers.PostgreSql
Install-Package Testcontainers.Redis
If you want to learn more about the basic setup, check out my article on integrating testing with Testcontainers.
Here's how to set up your containers with proper configuration:
PostgreSqlContainer _postgresContainer = new PostgreSqlBuilder()
.WithImage("postgres:17")
.WithDatabase("devhabit")
.WithUsername("postgres")
.WithPassword("postgres")
.Build();
RedisContainer _redisContainer = new RedisBuilder()
.WithImage("redis:latest")
.Build();
To start and stop containers cleanly across your test suite, implement IAsyncLifetime
in your WebApplicationFactory
:
public sealed class IntegrationTestWebAppFactory : WebApplicationFactory<Program>, IAsyncLifetime
{
public async Task InitializeAsync()
{
await _postgresContainer.StartAsync();
await _redisContainer.StartAsync();
// Start other dependencies here
}
public async Task DisposeAsync()
{
await _postgresContainer.StopAsync();
await _redisContainer.StopAsync();
}
}
This ensures containers are ready before tests run and cleaned up afterward. This means no leftover Docker state or race conditions.
A tip: pin your image versions (like postgres:17
) to avoid surprises from upstream changes
I learned this the hard way when a minor version update caused my tests to fail unexpectedly.
The biggest mistake I see is hardcoding connection strings. Testcontainers assigns dynamic ports. Don't hardcode anything.
Instead, inject values via WebApplicationFactory.ConfigureWebHost
:
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseSetting("ConnectionStrings:Database", _postgresContainer.GetConnectionString());
builder.UseSetting("ConnectionStrings:Redis", _redisContainer.GetConnectionString());
}
The key is to use the UseSetting
method to pass connection strings dynamically.
It also avoids any race conditions or conflicts with other tests that might run in parallel.
This ensures your tests always connect to the right ports, regardless of what Docker assigns.
There's no need to remove services from the service collection or manually configure them (contrary to what you might find online). Just set the connection strings, and your application will use them automatically.
What's a test fixture? A fixture is a shared context for your tests, allowing you to set up expensive resources like databases or message brokers once and reuse them across multiple tests.
This is where most teams get tripped up. The choice between class and collection fixtures affects both test performance and isolation.
Class Fixture - One container per test class:
Use class fixtures when tests modify global state or when debugging test interactions becomes difficult.
public class AddItemToCartTests : IClassFixture<DevHabitWebAppFactory>
{
private readonly DevHabitWebAppFactory _factory;
public AddItemToCartTests(DevHabitWebAppFactory factory)
{
_factory = factory;
}
[Fact]
public async Task Should_ReturnFailure_WhenNotEnoughQuantity() { ... }
}
Collection Fixture - One container shared across multiple test classes:
Use collection fixtures when your tests don't modify shared state or when you can reliably clean up between tests.
[CollectionDefinition(nameof(IntegrationTestCollection))]
public sealed class IntegrationTestCollection : ICollectionFixture<DevHabitWebAppFactory>
{
}
Then apply it to your test classes:
[Collection(nameof(IntegrationTestCollection))]
public class AddItemToCartTests : IntegrationTestFixture
{
public AddItemToCartTests(DevHabitWebAppFactory factory) : base(factory) { }
[Fact]
public async Task Should_ReturnFailure_WhenNotEnoughQuantity()
{
Guid customerId = await Sender.CreateCustomerAsync(Guid.NewGuid());
var command = new AddItemToCartCommand(customerId, ticketTypeId, Quantity + 1);
Result result = await Sender.Send(command);
result.Error.Should().Be(TicketTypeErrors.NotEnoughQuantity(Quantity));
}
}
When to use which:
With collection fixtures, you have to take care of cleaning up any state that might persist between tests. This could include resetting databases, clearing caches, or removing test data. If you don't do this, you risk tests affecting each other, leading to flaky results.
Your fixture can expose helpers to simplify test writing:
public async Task<HttpClient> CreateAuthenticatedClientAsync() { ... }
protected async Task CleanupDatabaseAsync() { ... }
These methods can handle authentication setup and database cleanup, so you don't have to repeat boilerplate code in every test. This lets your test code focus on assertions, not setup.
With the infrastructure properly configured, your actual tests should focus on business logic:
[Fact]
public async Task Should_ReturnFailure_WhenNotEnoughQuantity()
{
//Arrange
Guid customerId = await Sender.CreateCustomerAsync(Guid.NewGuid());
var eventId = Guid.NewGuid();
var ticketTypeId = Guid.NewGuid();
await Sender.CreateEventWithTicketTypeAsync(eventId, ticketTypeId, Quantity);
var command = new AddItemToCartCommand(customerId, ticketTypeId, Quantity + 1);
//Act
Result result = await Sender.Send(command);
//Assert
result.Error.Should().Be(TicketTypeErrors.NotEnoughQuantity(Quantity));
}
Notice how the tests focus on business rules rather than infrastructure concerns. The container complexity is hidden behind well-designed base classes and helper methods. You're not mocking Postgres or Redis, you're testing real behavior.
Testcontainers transforms integration testing by giving you the confidence that comes from testing against real dependencies. No more wondering if your in-memory database behavior matches production, or dealing with shared test environments that break when someone else runs their tests.
Start simple: pick one integration test that currently uses mocks or in-memory databases, and convert it to use Testcontainers. You'll immediately notice the difference in confidence when that test passes. Then gradually expand to cover your critical business flows.
If you want to learn how to structure your applications for testability from day one, my Pragmatic Clean Architecture course covers integration testing with Testcontainers alongside domain modeling, API design, and the architectural decisions that make applications maintainable over time.
That's all for today.
See you next week.
It’s the end of a busy week. I’m looking forward to a hopefully-quiet weekend with the family and a few good books. Take a breather too!
[article] How much does AI impact development speed? Good look at some new research into how much AI impacts developers and their pace. Interesting that seniority and prior usage didn’t change the outcome.
[blog] Veo 3: A Detailed Prompting Guide. This is absolutely fantastic. Get all the right phrases and jargon to use when prompting a text-to-video model like Veo 3. Gold!
[blog] Gemini CLI: Technical Assessment Report – AI Hacker Lab Technical Analysis. Wow, what a thorough analysis. We’re only 3 days into this product, but we’ve already shipped a few updates, and somehow became the most starred agentic CLI on GitHub.
[article] Walmart cracks enterprise AI at scale: Thousands of use cases, one framework. I liked some of the insights here, including an evolution of success metrics from funnels and conversion, to actual goal completion.
[blog] Coding agents have turned a corner. It’s fine when goofballs like me use these AI tools and offer guidance, but I really value the advice from capital-E Engineers like Brian. Here, he offers his direction on how to work with coding agents.
[blog] First steps with Gemini Code Assist agent mode. Excellent post that shows the workflow and tooling for using agents within your VS Code editor.
[blog] The rise of “context engineering.” The idea here is making sure the LLM has the right information and tools it needs to accomplish its task. It’s a system approach, versus thinking in prompts alone.
[blog] Introducing BigQuery ObjectRef: Supercharge your multimodal data and AI processing. This seems super cool and useful. Reference a binary object from within your structured tables and do single queries that can factor it all in.
[blog] The Google for Startups Gemini kit is here. Startups seem to gravitate towards Google, and we’re making it even better for them with this offering.
Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below: