xUnit adding Trait to CollectionDefinition - c#

In xUnit and Visual Studio, I would like to group tests marked with the [Collection("DB")] attribute in the Test Explorer. I can group test by the [Trait("Collection", "DB")] attribute only. Is there any way how to assign a specific Trait to all tests with [Collection("DB")] attribute?
Update: I have added xUnit issue #799.

Copied from http://mac-blog.org.ua/xunit-category-trait/.
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
using XunitCategoriesSample.Traits;
namespace XunitCategoriesSample.Traits
{
public class CategoryDiscoverer : ITraitDiscoverer
{
public const string KEY = "Category";
public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute)
{
var ctorArgs = traitAttribute.GetConstructorArguments().ToList();
yield return new KeyValuePair<string, string>(KEY, ctorArgs[0].ToString());
}
}
//NOTICE: Take a note that you must provide appropriate namespace here
[TraitDiscoverer("XunitCategoriesSample.Traits.CategoryDiscoverer", "XunitCategoriesSample")]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class CategoryAttribute : Attribute, ITraitAttribute
{
public CategoryAttribute(string category) { }
}
}
namespace XunitCategoriesSample
{
public class Class1
{
[Fact]
[Category("Jobsearcher")]
public void PassingTest()
{
Assert.Equal(4, Add(2, 2));
}
[Fact]
[Category("Employer")]
public void FailingTest()
{
Assert.Equal(5, Add(2, 2));
}
int Add(int x, int y)
{
return x + y;
}
}
}
NOTICE you must provide right namespaces in TraitDiscoverer attribute.
But here is more, lets make even more specialized attributes:
public class JobsearcherTraitDiscoverer : ITraitDiscoverer
{
public const string VALUE = "Jobsearcher";
public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute)
{
yield return new KeyValuePair<string, string>(CategoryDiscoverer.KEY, VALUE);
}
}
[TraitDiscoverer("XunitCategoriesSample.Traits.JobsearcherTraitDiscoverer", "XunitCategoriesSample")]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class JobsearcherTraitAttribute : Attribute, ITraitAttribute
{
public JobsearcherTraitAttribute()
{
}
}
So from now on you will be able to just type [JobsearcherTrait]
Links:
https://github.com/xunit/xunit/issues/394 - discussion about why TraitAttribute was marked as sealed
https://github.com/xunit/samples.xunit/tree/master/TraitExtensibility - sample by xunit how to make custom attributes
https://github.com/wespday/CategoryTraits.Xunit2 - one more sample
https://github.com/xunit/xunit/blob/47fdc2669ae6aa28f6d642e202840193dfc7dbd7/test/test.xunit.execution/Common/TraitHelperTests.cs - xunit test sample of implementing custom attributes

In the Xunit.Sdk.ITraitDiscoverer interface GetTraits method's argument 'traitAttribute' is having actual attribute value, but unfortunately the is no direct way to get it as Xunit.Abstractions.IAttributeInfo has no getter which is weird. Here is just another solution without calling GetConstructorArguments()
Enum for exact categories we need
public enum Category
{
UiSmoke,
ApiSmoke,
Regression
}
Custom attribute definition
[TraitDiscoverer("Automation.Base.xUnit.Categories.CategoryDiscoverer", "Automation.Base")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class TestCategoryAttribute : Attribute, ITraitAttribute
{
public string Category { get; }
public TestCategoryAttribute(Category category)
{
Category = category.ToString();
}
}
And here is the category resolver/discoverer
public sealed class CategoryDiscoverer : ITraitDiscoverer
{
public const string Key = "Category";
public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute)
{
var category = traitAttribute.GetNamedArgument<string>(Key);
yield return new KeyValuePair<string, string>(Key, category);
}
}
Here is the catch we need to know exact property name in the TestCategoryAttribute type, in discoverer its defined using Key constant.
Anyway, both GetConstructorArguments() and GetNamedArgument() are based on reflection, while discoverer is executed per each test once being run which is not that super-fast.

You can do this:
enum Collection {
DB,
File,
// Others
}
And later at class or method level:
[Trait(nameof(Collection), nameof(Collection.DB))]
Clean and simple

Related

Implement a dictionary of classes for a pseudo class factory

I´m trying to buld a class factory like that:
public class Toyota() {};
public class Bmw() {};
public class Mercedes() {};
public class BrandFactory
{
private Dictionary<string, object> _Brands = new Dictionary<string, object> {
{"Toyota", Toyota},
{"Bmw", Bmw},
{"Mercedes", Mercedes}
}
public object GetBrand(string brandName)
{
return = BusinessManagers[brandName].Invoke;
}
}
This is the idea, but it´s not working - I can´t even compile the above code as the Dictionary cannot associate an 'object' with the function. I tried Func<> as well, but in that case it requires a previous type.
So, here are my questions:
Is that a correct way to implement this 'pseudo factory' ? The code came from the example at example code
If so, what needs to be fixed in the above code ?
The reason I´m asking that is because I need to create a new object based on a string that is received from a cliente application using Ajax. Like:
AjaxCall -> String Containing Object Name -> Object Inoke -> Method Call -> Send result back to client
The Method Call is a standard for all implementation of Brand.
Please can someone help me with that ?
Thanks.
You have a several options here. If you end up using a Dictionary, I recommend making it case-insensitive and taking care to avoid KeyNotFoundExceptions.
public class CaseInsensitiveStringComparer : IComparer<string>
{
public int Compare(string x, string y)
{
return string.Compare(x, y, ignoreCase: true);
}
}
The first option is to use Dictionary<string, Func<object>>.
private IDictionary<string, Func<object>> _Brands
= new Dictionary<string, Func<object>> (new CaseInsensitiveStringComparer())
{
{"Toyota", () => new Toyota() },
{"BMW", () => new Bmw() },
{"Mercedes", () => Mercedes() }
};
public object GetBrand(string brandName)
{
Func<object> func;
return _Brands.TryGetValue(brandName, out func)
? func() // invoking the delegate creates the instance of the brand object
: null; // brandName was not in the dictionary
}
Second option is to use Activator. You can use a Dictionary<string,Type>, but it may not be necessary if your type name matches the string (see notes below).
public object GetBrand(string brandName)
{
Type type;
return _Brands.TryGetValue(brandName, out type)
? Activator.CreateInstance(type) // activator invokes a parameterless constructor
: null; // brandName was not in the dictionary
}
// vs.
return Activator.CreateInstance(null, brandName).Unwrap();
// Case sensitivity would be an issue here.
// Security could be an issue here.
// Creating objects based directly off of user input means any class
// from any referenced assembly could be created if a hacker can learn
// out the namespaces and class names.
Third option is to use an IoC container to do the resolution. This gives you some flexibility with lifetime management.
The second approach currently assumes a parameterless constructor, wherease the first and third would allow for disparate constructor signatures.
In all cases, the result is simply object, which gives this approach limited utility. If all of these "brand" classes could share a common interface, then you could use IBrand or whatever in your Dictionary and as the return type.
I'm checking for bad data (values not in the Dictionary) and returning null; you could choose to throw an Exception if that makes more sense for your use case.*
You do not need a Dictionary at all:
public class DynamicFactory<T>
{
public static T Create(string className)
{
Type t = typeof(T);
return (T)Activator.CreateInstance(
t.Assembly.FullName,
t.Namespace + "." + className
).Unwrap();
}
}
namespace Brands
{
public class CarBrand { }
// The brands should be in the same namespace and assembly with CarBrand
// and should inherit from CarBrand
public class Toyota : CarBrand { };
public class Bmw : CarBrand { };
public class Mercedes : CarBrand { };
public class Titanic { } // this one is not CarBrand
class BrandFactory: DynamicFactory<CarBrand> { }
// Below are unit tests using NUnit
namespace BrandFactorySpecification
{
static class Create
{
[TestCase("Toyota", Result = typeof(Toyota))]
[TestCase("Bmw", Result = typeof(Bmw))]
[TestCase("Mercedes", Result = typeof(Mercedes))]
[TestCase("Titanic", ExpectedException = typeof(InvalidCastException))]
[TestCase("unknown", ExpectedException = typeof(TypeLoadException))]
[TestCase("String", ExpectedException = typeof(TypeLoadException))]
[TestCase("System.String", ExpectedException = typeof(TypeLoadException))]
[TestCase("ACarBrandFromAnotherNamespace",
ExpectedException = typeof(TypeLoadException))]
[TestCase("AnotherNamespace.ACarBrandFromAnotherNamespace",
ExpectedException = typeof(TypeLoadException))]
//
public static Type ShouldReturnCorrectType(string brandName)
{
return BrandFactory.Create(brandName).GetType();
}
[Test]
public static void ForTitanic()
{
DynamicFactory<Titanic>.Create("Titanic")
.ShouldBeType(typeof(Titanic));
}
}
namespace AnotherNamespace
{
public class ACarBrandFromAnotherNamespace : CarBrand { };
}
}
}
Update: the code was improved in the following ways:
The security problem, mentioned in the comments was fixed
flexibility improved
A new generic class DynamicFactory<T> now can be reused elsewhere
Brands can be located in other namespace and assembly then BrandFactory
Unit tests were added to serve as examples of usage and specification (using NUnit required for them)
That's not at all how a factory works. First of all you need a superclass that can be the parent of your car models:
public class CarModel() {};
public class Toyota() : CarModel {};
public class Bmw() : CarModel {};
public class Mercedes() : CarModel {};
Now you can create a factory that returns the correct model:
public class BrandFactory
{
public T GetBrand<T>() where T : CarModel
{
return new T();
}
}
Now when you want to create a object its is simple:
var factory = new BrandFactory();
var bmw = factory.GetBrand<Bmw>();

How to share a static method amongst several class

I'd like to start with something like this:
class A { ... }
class B { ... }
class C { ... }
Where A, B and C have a static method MyName.
Then I could do:
Console.WriteLine(A.MyName());
Console.WriteLine(B.MyName());
Console.WriteLine(C.MyName());
Then after I should be able to do something like this.
foreach(var type in new[] { typeof(A), typeof(B), typeof(C)) {
??? Console.WriteLine(t.MyName());
}
How could I do that?
I'd also like to be able to do the following (but that may be impossible):
??? x = new A();
Console.WriteLine(x.MyName());
x = new B();
Console.WriteLine(x.MyName());
What you're trying to do here is associate Metadata with a type, which can be queried if you know the type. The standard practice for doing this is to use Custom Attributes. You can query these attributes in a type-safe way and extract the associated information for each attribute. They are quite flexible in how you specify their inheritance and whether you can apply more than one of the same attribute type. They can also be applied to other things besides classes, like properties or fields, which can be handy.
Here's a simple demo program (the null check isn't strictly necessary here, but just demonstrating how you check whether an attribute actually exists.) Note that the extension method that provides a generic GetCustomAttribute was only added in .NET 4.5. Prior versions will require you to use a non-generic version and cast it to the appropriate attribute type.
class Program
{
static void Main(string[] args)
{
var types = new[] {typeof(A), typeof(B), typeof(C)};
foreach (var type in types)
{
var attribute = type.GetCustomAttribute<NameAttribute>();
if (attribute != null)
Console.WriteLine(attribute.Name);
}
Console.ReadLine();
}
public sealed class NameAttribute : Attribute
{
public string Name { get; private set; }
public NameAttribute(string name)
{
Name = name;
}
}
[Name("A Name")]
public class A
{
}
[Name("B Name")]
public class B
{
}
[Name("C Name")]
public class C
{
}
}
In order to share some static member between classes you need to inherit from base class which will contain static member:
public class Base
{
public static string MyName() { return "Bob"; }
}
public class A : Base
{
}
public class B : Base
{
}
You can't do what you are trying in your foreach loop, because variable t has type Type and Type do not have any MyName properties. You should use reflection to get MyName value:
Console.WriteLine(A.MyName()); // Bob
Console.WriteLine(B.MyName()); // Bob
foreach(var type in new[] { typeof(A), typeof(B) })
{
var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy;
var method = type.GetMethod("MyName", flags);
Console.WriteLine(method.Invoke(null, null));
}
This code prints Bob for both types.

Cannot Add class in Enum.Extensions namespace, because Enum type (System) is then inavailable

I have two projects.
1) One (library) that contains Enum extension methods in namespace:
namespace Enum.Extensions
{
public static class EnumerationExtensions
{
public static bool Has<T>(this System.Enum type, T value)
{
try
{
return (((int)(object)type & (int)(object)value) == (int)(object)value);
}
catch
{
return false;
}
}
}
}
2) Second, Console Applications which has a reference to the library above and tries to use
its new methods:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Enum.Extensions;
namespace XMLExtensionsTest
{
public enum ProcesInfo
{
ifCreate = 1,
ifRun1 = 2,
IfRun2 = 4,
IFRun3 = 8
}
class Program
{
static void Main(string[] args)
{
ProcesInfo enumInfo = ProcesInfo.ifCreate;
enumInfo = enumInfo.Add(ProcesInfo.IfRun2);
bool value = enumInfo.Has(ProcesInfo.ifCreate);
bool value2 = enumInfo.Has(ProcesInfo.ifRun1);
bool value3 = enumInfo.Has(ProcesInfo.IfRun2);
bool value4 = enumInfo.Has(ProcesInfo.IFRun3);
}
}
}
Now, because of that Extensions class all standard Enum types are not accessible.
i cannot write:
public void Test(Enum test)
{
}
but need:
public void Test(System.Enum test)
{
}
There are thousands of places where Enum is used without "System".
How to add Extensions class without touching existing Enum class calls?
Thanks!
You can do any one of the following three options, #3 is your best bet if you do not/cannot change the namespace
Rename your Enum.Extensions name space
Prefix it with something like MyStuff.Enum.Extensions
Alias it like using MyAlias = Enum.Extensions
You will need to change the namespace of the Enum Library. Which is your first library project having Extensions.
Enum is the Type name and you are using it as a namespace and hence there is ambiguity.

How would you unit test data annotations?

Two of the class properties have the following annotations:
[Key]
[Column]
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[MaxLength(25)]
public string Name { get; set; }
I understand that testing Key, Column and Required attributes is no longer a unit test, it's an integration test as it would depend on the underlying database, but how do you go about testing MaxLength(25) attribute?
One of the alternatives that I can think of, is to add a code contract into the property.
Update
As suggested, I wrote the following helper:
public class AttributeHelper <T> where T : class
{
private Type GivenClass
{
get { return typeof (T); }
}
public bool HasAnnotation(Type annotation)
{
return GivenClass.GetCustomAttributes(annotation, true).Single() != null;
}
public bool MethodHasAttribute(Type attribute, string target)
{
return GivenClass.GetMethod(target).GetCustomAttributes(attribute, true).Count() == 1;
}
public bool PropertyHasAttribute(Type attribute, string target)
{
return GivenClass.GetProperty(target).GetCustomAttributes(attribute, true).Count() == 1;
}
}
I have then tested my helper:
[TestMethod]
public void ThisMethod_Has_TestMethod_Attribute()
{
// Arrange
var helper = new AttributeHelper<AttributeHelperTests>();
// Act
var result = helper.MethodHasAttribute(typeof (TestMethodAttribute), "ThisMethod_Has_TestMethod_Attribute");
// Assert
Assert.IsTrue(result);
}
Everything works fine, apart from the fact that methods and properties must be public in order for me to use reflection. I can't think of any cases where I had to add attributes to the private properties/methods.
And then testing the EF annotations:
public void IdProperty_Has_KeyAttribute()
{
// Arrange
var helper = new AttributeHelper<Player>();
// Act
var result = helper.PropertyHasAttribute(typeof (KeyAttribute), "Id");
// Assert
Assert.IsTrue(result);
}
I understand that testing Key, Column and Required attributes is no longer a unit test, it's an integration test as it would depend on the underlying database
How is that so? You can test whether Id property is marked with all those attributes just fine. And it falls into unit-test category.
[Test]
public void Id_IsMarkedWithKeyAttribute()
{
var propertyInfo = typeof(MyClass).GetProperty("Id");
var attribute = propertyInfo.GetCustomAttributes(typeof(KeyAttribute), true)
.Cast<KeyAttribute>()
.FirstOrDefault();
Assert.That(attribute, Is.Not.Null);
}
This way you can assure your properties are marked with any attribute you can think of. Sure, this involves some reflection work but that's how you test attribute marking.

Can ProtoBuf-Net deserialize to a flat class?

protobuf-net uses nested protobuf constructs to support inheritance. However, can it be made to push properties into a flat target class that has the same properties as the inherited "serialized" version?
See the test example below. Needless to say the result of the Flat namespace is null for both properties.
Possible solution: copy data into flat.B first on a property by property basis.
Note: this is not the prefered option.
using System;
namespace hierarchy
{
using ProtoBuf;
[ProtoContract]
public class A
{
[ProtoMember(1)]
public string prop1 { get; set; }
}
[ProtoContract]
public class B : A
{
public B()
{
}
[ProtoMember(1)]
public string prop2 { get; set; }
public override string ToString()
{
return "prop1=" + prop1 + ", prop2=" + prop2;
}
}
}
namespace flat
{
using ProtoBuf;
[ProtoContract]
public class B
{
[ProtoMember(1)]
public string prop1 { get; set; }
[ProtoMember(2)]
public string prop2 { get; set; }
public override string ToString()
{
return "prop1=" + prop1 + ", prop2=" + prop2;
}
}
}
namespace TestProtoSerialization
{
using ProtoBuf;
using System.IO;
public class Test2
{
public void Test()
{
var hb = new hierarchy.B();
hb.prop1 = "prop1";
hb.prop2 = "prop2";
var ms = new MemoryStream();
Serializer.Serialize<hierarchy.B>(ms, hb);
var flatB = Serializer.Deserialize<flat.B>(ms);
Console.WriteLine(hb.ToString()); // <----- Output: prop1=prop1, prop2=prop2
Console.WriteLine(flatB.ToString()); // <----- Output: prop1=, prop2=
}
}
public class Program
{
private static void Main(string[] args)
{
var o2 = new Test2();
o2.Test();
}
}
}
Not directly, and I'm not sure there is a great need to. Maybe I am missing something in the example...
To pick up on the key point - even forgetting about inheritance you've broken the contract - te fields in your exampl are 1 & 1 in one model and 1 & 2 in the other.
It really depends what your objective is; if you just want to push the data over, then sure you can set up a RuntimeTypeModel that only knows about the derived type (disable automatic configuration and add the fields manually). This will then only work for the derived type (obviously), but will output the data as expected by the flat model:
var model = TypeModel.Create();
model.Add(typeof(B), false)
.Add("prop1", "prop2");
Then use model.Serialize etc.
However, writing a flat conversion method on c#, or using AutoMapper would be more obvious. I would only use the above if my objective is to remove the inheritance from the output, for example for interoperability reasons.

Categories