Skip to content
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

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
Draft

Conversation

amerjusupovic
Copy link
Member

First draft of integration testing using copilot

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)
Copy link
Member

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))
Copy link
Member

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.
Copy link
Member

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}",
Copy link
Member

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";
Copy link
Member

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";
Copy link
Member

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";
Copy link
Member

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()
Copy link
Member

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)
Copy link
Member

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"]);
Copy link
Member

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);
Copy link
Member

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();
Copy link
Member

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)
Copy link
Member

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)
Copy link
Member

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()
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants