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 unit tests to aws-csharp #867

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions aws-csharp/${PROJECT}.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<DefaultItemExcludes>$(DefaultItemExcludes);tests/**/*.cs;sdks/**/*.cs</DefaultItemExcludes>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more idiomatic thing to do would be to have the program and test projects SxS:

proj/
├── Pulumi.yaml
├── Program.cs
└── proj.csproj
tests/
├── InfraTests.cs
└── Tests.csproj

But we can't easily do that from a template. If we structured the template like this, you wouldn't be able to run pulumi up after pulumi new because the program would live in a subdirectory. You'd have to cd into the program's subdirectory first.

I think we want to keep it such that you can run pulumi up immediately after pulumi new, without having to change directories. So we nest the test project:

proj/
├── Pulumi.yaml
├── Program.cs
├── proj.csproj
└── tests/
    ├── InfraTests.cs
    └── Tests.csproj

To do so, we have to exclude the source files in the nested project here.

We have a similar issue with parameterized providers, where pulumi package add generates the sdks in a sdks subdirectory, and we ask users to add <DefaultItemExcludes> for that. For that reason, I've included excludes for both sdks/ and tests/ by default.

</PropertyGroup>

<ItemGroup>
Expand Down
29 changes: 20 additions & 9 deletions aws-csharp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,25 @@
using Pulumi.Aws.S3;
using System.Collections.Generic;

return await Deployment.RunAsync(() =>
{
// Create an AWS resource (S3 Bucket)
var bucket = new BucketV2("my-bucket");
return await Deployment.RunAsync(Deploy.Infra);

// Export the name of the bucket
return new Dictionary<string, object?>
public static class Deploy
{
public static Dictionary<string, object?> Infra()
{
["bucketName"] = bucket.Id
};
});
// Create an AWS resource (S3 Bucket) with tags.
var bucket = new BucketV2("my-bucket", new()
{
Tags =
{
{ "Name", "My bucket" },
},
});

// Export the name of the bucket.
return new Dictionary<string, object?>
{
["bucketName"] = bucket.Id
};
}
}
65 changes: 65 additions & 0 deletions aws-csharp/tests/InfraTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Pulumi;
using Pulumi.Aws.S3;
using Pulumi.Testing;
using Xunit;

public static class TestingExtensions
{
// Test helper to convert a Pulumi Output to a Task.
// This should only be used in tests.
public static Task<T> GetValueAsync<T>(this Output<T> output)
=> Pulumi.Utilities.OutputUtilities.GetValueAsync(output);
}

class Mocks : IMocks
{
// Mock calls to create new resources and return a canned response.
public Task<(string? id, object state)> NewResourceAsync(MockResourceArgs args)
{
// Here, we're returning a same-shaped object for all resource types.
// We could, however, use the arguments passed into this function to
// customize the mocked-out properties of a particular resource.
// See the unit-testing docs for details:
// https://www.pulumi.com/docs/iac/concepts/testing/unit/
return Task.FromResult<(string?, object)>(($"{args.Name}_id", (object)args.Inputs));
}

// Mock function calls and return an empty response.
public Task<object> CallAsync(MockCallArgs args)
{
return Task.FromResult((object)ImmutableDictionary<string, object>.Empty);
}
}

public class InfraTests
{
class TestStack : Stack
{
public TestStack()
{
Outputs = Deploy.Infra();
}

public Dictionary<string, object?> Outputs { get; set; }
}

private static Task<ImmutableArray<Resource>> TestAsync()
=> Deployment.TestAsync<TestStack>(new Mocks(), new TestOptions { IsPreview = false });


// Example test. To run, uncomment and run `dotnet test` from the tests directory.
// [Fact]
// public async Task TestBucketTags()
// {
// var resources = await TestAsync();
// var bucket = resources.OfType<BucketV2>().Single();

// var tags = await bucket.Tags.GetValueAsync();
// Assert.NotNull(tags);
// Assert.Contains("Name", tags);
// }
}
20 changes: 20 additions & 0 deletions aws-csharp/tests/Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\${PROJECT}.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Pulumi" Version="3.*" />
<PackageReference Include="Pulumi.Aws" Version="6.*" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="xunit.v3" Version="0.7.0-pre.15" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.0-pre.49" />
</ItemGroup>

</Project>
Loading