-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add integration testing #634
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR Overview
This PR introduces the first draft for integration testing using Copilot. The changes in this PR primarily involve reordering the using directives in two configuration files.
- Updated using statements ordering in ConfigurationSettingPageExtensions.cs.
- Updated using statements ordering in IConfigurationSettingPageIterator.cs.
Reviewed Changes
File | Description |
---|---|
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/ConfigurationSettingPageExtensions.cs | Reordered using directives |
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/IConfigurationSettingPageIterator.cs | Reordered using directives |
Copilot reviewed 21 out of 21 changed files in this pull request and generated no comments.
} | ||
} | ||
} | ||
catch (Exception ex) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never catch base exception.
{ | ||
string localSettingsPath = Path.Combine(AppContext.BaseDirectory, LocalSettingsFile); | ||
|
||
if (File.Exists(localSettingsPath)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the tests run without the file?
{ | ||
/// <summary> | ||
/// Integration tests for Azure App Configuration that connect to a real service. | ||
/// Creates a temporary App Configuration store for testing and deletes it after the tests are complete. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How are stale stores cleaned up?
new ConfigurationSetting(SentinelKey, "Initial"), | ||
ConfigurationModelFactory.ConfigurationSetting( | ||
FeatureFlagKey, | ||
@"{""id"":""" + TestKeyPrefix + @"Feature"",""description"":""Test feature"",""enabled"":false}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The @
looks unnecessary here.
private const string LocationEnvVar = "AZURE_LOCATION"; | ||
private const string CreateResourceGroupEnvVar = "AZURE_CREATE_RESOURCE_GROUP"; | ||
private const string DefaultLocation = "eastus"; | ||
private const string LocalSettingsFile = "local.settings.json"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We typically use appsettings.json or appsettings.test.json
// Azure Resource Management constants | ||
private const string ResourceGroupEnvVar = "AZURE_APPCONFIG_RESOURCE_GROUP"; | ||
private const string SubscriptionIdEnvVar = "AZURE_SUBSCRIPTION_ID"; | ||
private const string LocationEnvVar = "AZURE_LOCATION"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there really a desire to run from env variable?
private const string SubscriptionIdEnvVar = "AZURE_SUBSCRIPTION_ID"; | ||
private const string LocationEnvVar = "AZURE_LOCATION"; | ||
private const string CreateResourceGroupEnvVar = "AZURE_CREATE_RESOURCE_GROUP"; | ||
private const string DefaultLocation = "eastus"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's pick a low traffic region.
/// <summary> | ||
/// Cleans up the temporary App Configuration store after tests are complete. | ||
/// </summary> | ||
public async Task DisposeAsync() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should have Cleanup method that we call on intialization and tear down. That way we don't have stale stores.
await _appConfigStore.DeleteAsync(WaitUntil.Completed); | ||
} | ||
|
||
if (_shouldDeleteResourceGroup && _resourceGroup != null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think we'll ever want to delete the resource group?
.Build(); | ||
|
||
// Verify initial values | ||
Assert.Equal("InitialValue1", config[$"{keyPrefix}:Setting1"]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should have one or multiple pre-cache expiration calls to ensure that the keys aren't refreshed until the cache expiration is up. That way cache expiration both ways can be tested here.
[Fact] | ||
public void LoadConfiguration_RetrievesValuesFromAppConfiguration() | ||
{ | ||
Skip.If(_skipTests, _skipReason); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really understand why we'd want skip. If an exception occurs during initialization, just let it bubble and blow up.
await Task.Delay(TimeSpan.FromSeconds(2)); | ||
|
||
// Act | ||
var result = await refresher.TryRefreshAsync(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use RefreshAsync instead of Try.
// Only refresh Setting1 when sentinel changes | ||
options.ConfigureRefresh(refresh => | ||
{ | ||
refresh.Register(sentinelKey, $"{keyPrefix}:Setting1", refreshAll: false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this registering a key with a label $"{keyPrefix}:Setting1"
? That looks wrong.
/// <summary> | ||
/// Setup test-specific keys and settings | ||
/// </summary> | ||
private async Task<(string keyPrefix, string sentinelKey, string featureFlagKey)> SetupTestKeys(string testName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid returning tuples.
} | ||
|
||
[Fact] | ||
public async Task RegisterAll_RefreshesAllKeys_WhenSentinelChanged() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sentinel and refresh all are two completely different paths. I don't see a reason to mix them.
First draft of integration testing using copilot