Skip to content

Commit

Permalink
[andrewabestGH-87] Added new convention to check that an assembly is …
Browse files Browse the repository at this point in the history
…included (by name) in a haystack set of assemblies

This can be used to ensure a list of assemblies (e.g. those containing "production code") is kept up-to-date *so that you can apply conventions to the types in those assemblies*.
  • Loading branch information
eddie.stanley committed Jan 6, 2024
1 parent 4239440 commit 4a96fd6
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using Conventional.Extensions;
using FluentAssertions;
using NUnit.Framework;

Expand Down Expand Up @@ -185,5 +185,39 @@ public void MustHaveCertainFilesBeContentCopyIfNewer_Regex()
result.IsSatisfied.Should().BeFalse();
result.Failures.Single().Should().EndWith("copy-not.png");
}

private AssemblySpecimen[] TestProjects =>
AllAssemblies.WithNamesMatching("*")
.Where(specimen => specimen.ProjectFilePath.Contains("Tests"))
.ToArray();

// Note: In practice, this list of assemblies would be used to drive further convention tests (i.e. assembly.GetTypes())
private static readonly List<Assembly> TestAssemblies = new List<Assembly>
{
typeof(DogFoodConventions).Assembly
};

[Test]
public void MustBeIncludedInSetOfAssemblies_Success()
{
var result = TestProjects
.MustConformTo(Convention.MustBeIncludedInSetOfAssemblies(TestAssemblies, "TestAssemblies"));

// TODO: Use result.Should().AllSatisfy() once we've updated to fluentassertions 6.5.0+
result.Select(x => x.IsSatisfied).Distinct().Single().Should().BeTrue();
}

[Test]
public void MustBeIncludedInSetOfAssemblies_Failure()
{
// ReSharper disable once CollectionNeverUpdated.Local
var staleTestAssemblies = new List<Assembly>();

var result = TestProjects
.MustConformTo(Convention.MustBeIncludedInSetOfAssemblies(staleTestAssemblies, "TestAssemblies"));

// TODO: Use result.Should().AllSatisfy() once we've updated to fluentassertions 6.5.0+
result.Select(x => x.IsSatisfied).Distinct().Single().Should().BeFalse();
}
}
}
14 changes: 14 additions & 0 deletions src/Core/Conventional/Convention.Assembly.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.RegularExpressions;
using Conventional.Conventions.Assemblies;

Expand Down Expand Up @@ -67,5 +69,17 @@ public static MustIncludeAllMatchingFilesInFolderConventionSpecification MustInc
{
return new MustIncludeAllMatchingFilesInFolderConventionSpecification(filePattern, subfolder);
}

/// <summary>
/// Require this assembly to be included (by name) in a list of assemblies (e.g. "TestAssemblies")
/// </summary>
/// <param name="assemblies">The "haystack" set of assemblies that the "needle" assembly must appear in</param>
/// <param name="setName">A friendly name for the assembly set</param>
/// <remarks>Probably only useful when using <see cref="AssemblySpecimen"/> i.e. <see cref="TheAssembly"/> / <see cref="AllAssemblies"/></remarks>
public static MustBeIncludedInSetOfAssembliesConventionSpecification MustBeIncludedInSetOfAssemblies(
IEnumerable<Assembly> assemblies, string setName)
{
return new MustBeIncludedInSetOfAssembliesConventionSpecification(assemblies, setName);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;

namespace Conventional.Conventions.Assemblies
{
public class MustBeIncludedInSetOfAssembliesConventionSpecification : AssemblyConventionSpecification
{
private readonly ISet<string> _assemblyNames;
private readonly string _assemblySetName;

public MustBeIncludedInSetOfAssembliesConventionSpecification(IEnumerable<Assembly> assemblyNames, string assemblySetName)
{
_assemblyNames = new HashSet<string>(assemblyNames.Select(assembly => assembly.GetName().Name));
_assemblySetName = assemblySetName;
}

protected override ConventionResult IsSatisfiedByLegacyCsprojFormat(string assemblyName, XDocument projectDocument)
{
return IsSatisfiedBy(assemblyName, projectDocument);
}

protected override ConventionResult IsSatisfiedBy(string assemblyName, XDocument projectDocument)
{
if (_assemblyNames.Contains(assemblyName))
{
return ConventionResult.Satisfied(assemblyName);
}

return ConventionResult.NotSatisfied(assemblyName, string.Format(FailureMessage, assemblyName));
}

protected override string FailureMessage => "{0} is not included in " + _assemblySetName;
}
}

0 comments on commit 4a96fd6

Please sign in to comment.