Testing Fabrics

Short of actually creating a project that covers all of the bases that one would want to cover is there a way to test fabrics present in Metalama that I have somehow missed?
10 Replies
Petr Onderka
Petr Onderka2y ago
You should be able to use the regular Metalama.Testing.AspectTesting approach to test fabrics too. Each test file is effectively treated as a separate project.
addabis
addabis2y ago
If you'd like to test that the fabric correctly works across projects, you can use the <Test>.Dependency.cs which causes the test runner to create two projects - the first project that includes <Test>.cs and references the second project which contains <Test>.Dependency.cs.
domsinclair
domsinclair2y ago
Indeed that does seem to work, thanks. @addabis I have a whole set of fabric extensions that I'd like to test, so it may well be that your suggestion would make eminent sense in this case. Is there an example of that anywhere in the documentation?
addabis
addabis2y ago
I don't think it's used in public repos at the moment. I'm mentioning that since it's rather a small note in https://doc.metalama.net/conceptual/aspects/testing/aspect-testing under "Creating a dependent project". We use that quite extensively though.
domsinclair
domsinclair2y ago
Your right about it being a small note, however let's see if I can make sense of it. This was the first test that I created;
c#
using Metalama.Framework.Aspects;
using Metalama.Framework.Code;
using Metalama.Framework.Fabrics;

namespace VtlSoftware.Logging.Tests
{
internal class LogAllPublicMethodsTest1
{
#region Private Methods
private void DoSomethingElse()
{
}

#endregion

#region Public Methods
public int Add(int a, int b) { return a + b; }
public void DoSomething()
{
}

#endregion
}

internal class Fabric : ProjectFabric
{
#region Public Methods
public override void AmendProject(IProjectAmender amender) { amender.LogAllPublicMethods(); }

#endregion
}

[CompileTime]
public static class FabricExtensions
{
#region Public Methods

public static void LogAllPublicMethods(this IProjectAmender amender)
{
amender.Outbound
.SelectMany(compilation => compilation.AllTypes)
.Where(
type => type.Accessibility is Accessibility.Public or Accessibility.Internal &&
!type.IsStatic ||
type.Attributes.OfAttributeType(typeof(NoLogAttribute)).Any())
.SelectMany(type => type.Methods)
.Where(method => method.Accessibility is Accessibility.Public && method.Name != "ToString")
.AddAspectIfEligible<LogMethodAttribute>();
}

#endregion
}
}
c#
using Metalama.Framework.Aspects;
using Metalama.Framework.Code;
using Metalama.Framework.Fabrics;

namespace VtlSoftware.Logging.Tests
{
internal class LogAllPublicMethodsTest1
{
#region Private Methods
private void DoSomethingElse()
{
}

#endregion

#region Public Methods
public int Add(int a, int b) { return a + b; }
public void DoSomething()
{
}

#endregion
}

internal class Fabric : ProjectFabric
{
#region Public Methods
public override void AmendProject(IProjectAmender amender) { amender.LogAllPublicMethods(); }

#endregion
}

[CompileTime]
public static class FabricExtensions
{
#region Public Methods

public static void LogAllPublicMethods(this IProjectAmender amender)
{
amender.Outbound
.SelectMany(compilation => compilation.AllTypes)
.Where(
type => type.Accessibility is Accessibility.Public or Accessibility.Internal &&
!type.IsStatic ||
type.Attributes.OfAttributeType(typeof(NoLogAttribute)).Any())
.SelectMany(type => type.Methods)
.Where(method => method.Accessibility is Accessibility.Public && method.Name != "ToString")
.AddAspectIfEligible<LogMethodAttribute>();
}

#endregion
}
}
I currently have seven fabric extensions that I'd like to test, and to do that properly I'd need to have a variety of different class signatures and method signatures for them to run over.
I now know that I can create separate tests for each scenario, I'm wondering if your suggestion would allow them all to be tested at once in some way.
addabis
addabis2y ago
My suggestion was intended only for the cross assembly scenario, i.e. when it is relevant that your fabric is being inherited in another project than the one in which it was applied. If you need to share code between test cases, you might want to have a look at the "Include other files" section. But the target code (the transformed code you are testing aspects on) always needs to be a part of the test file and cannot be shared between tests.
Gael Fraiteur
Gael Fraiteur2y ago
GitHub
Metalama.Extensions/src/Metalama.Extensions.Architecture at master ...
Open-source extensions to Metalama.Framework. Contribute to postsharp/Metalama.Extensions development by creating an account on GitHub.
Gael Fraiteur
Gael Fraiteur2y ago
GitHub
Metalama.Extensions/src/tests/Metalama.Extensions.Architecture.Aspe...
Open-source extensions to Metalama.Framework. Contribute to postsharp/Metalama.Extensions development by creating an account on GitHub.
Gael Fraiteur
Gael Fraiteur2y ago
@domsinclair Can we close this conversation?
domsinclair
domsinclair2y ago
Yes, certainly.
Want results from more Discord servers?
Add your server