Permalink
Browse files

code refactoring after merging in abstract class feature

  • Loading branch information...
2 parents 4bfa43e + 7666f9a commit 6ea01c1c971809b981f065d5a5ccb0eca83d2ec2 @amirrajan amirrajan committed Dec 23, 2011
View
@@ -82,17 +82,22 @@ public Conventions Initialize()
public MethodInfo GetMethodLevelBefore(Type type)
{
- return type.Methods().FirstOrDefault(s => specification.Before.IsMatch(s.Name) );
+ return GetMethodMatchingRegex(type, specification.Before);
}
public MethodInfo GetMethodLevelAct(Type type)
{
- return type.Methods().FirstOrDefault(s => specification.Act.IsMatch(s.Name));
+ return GetMethodMatchingRegex(type, specification.Act);
}
public MethodInfo GetMethodLevelAfter(Type type)
{
- return type.Methods().FirstOrDefault(s => specification.After.IsMatch(s.Name));
+ return GetMethodMatchingRegex(type, specification.After);
+ }
+
+ private MethodInfo GetMethodMatchingRegex(Type type, Regex regex)
+ {
+ return type.Methods().Where(mi => mi.DeclaringType == type).FirstOrDefault(mi => regex.IsMatch(mi.Name));
}
public bool IsMethodLevelExample(string name)
@@ -1,40 +1,60 @@
using System;
+using System.Linq;
using System.Collections.Generic;
+using System.Reflection;
using NSpec.Domain.Extensions;
namespace NSpec.Domain
{
public class ClassContext : Context
{
- private void BuildMethodLevelBefore()
+ private readonly List<Type> classHierarchyToClass = new List<Type>();
+
+ private IEnumerable<MethodInfo> GetMethodsFromHierarchy(Func<Type, MethodInfo> methodAccessor)
{
- var before = conventions.GetMethodLevelBefore(type);
+ return classHierarchyToClass.Select(methodAccessor).Where(mi => mi != null);
+ }
- if (before != null) BeforeInstance = i => before.Invoke(i, null);
+ private void BuildMethodLevelBefore()
+ {
+ var befores = GetMethodsFromHierarchy(conventions.GetMethodLevelBefore).ToList();;
+ if(befores.Count > 0)
+ {
+ BeforeInstance = instance => befores.Do(b => b.Invoke(instance, null));
+ }
}
private void BuildMethodLevelAct()
{
- var act = conventions.GetMethodLevelAct(type);
-
- if (act != null) ActInstance = i => act.Invoke(i, null);
+ var acts = GetMethodsFromHierarchy(conventions.GetMethodLevelAct).ToList();;
+ if(acts.Count > 0)
+ {
+ ActInstance = instance => acts.Do(a => a.Invoke(instance, null));
+ }
}
private void BuildMethodLevelAfter()
{
- var after = conventions.GetMethodLevelAfter(type);
-
- if (after != null) AfterInstance = i => after.Invoke(i, null);
+ var afters = GetMethodsFromHierarchy(conventions.GetMethodLevelAfter).Reverse().ToList();;
+ if(afters.Count > 0)
+ {
+ AfterInstance = instance => afters.Do(a => a.Invoke(instance, null));
+ }
}
public ClassContext(Type type, Conventions conventions = null, Tags tagsFilter = null, string tags = null)
- : base(type.Name, tags)
+ : base(type.CleanName(), tags)
{
this.type = type;
this.conventions = conventions ?? new DefaultConventions().Initialize();
this.tagsFilter = tagsFilter;
+
+ if (type != typeof(nspec))
+ {
+ classHierarchyToClass.AddRange(type.GetAbstractBaseClassChainWithClass());
+ }
}
public override void Build(nspec instance = null)
@@ -54,6 +74,11 @@ public override void Build(nspec instance = null)
public override bool IsSub(Type baseType)
{
+ while (baseType != null && baseType.IsAbstract)
+ {
+ baseType = baseType.BaseType;
+ }
+
return baseType == type;
}
@@ -18,11 +18,35 @@ public static IEnumerable<MethodInfo> Methods(this Type type)
var exclusions = typeof(nspec).GetMethods(flags).Select(m => m.Name);
- var methodInfos = type.GetMethods(flags);
+ var methodInfos = type.GetAbstractBaseClassChainWithClass().SelectMany(t => t.GetMethods(flags));;
+
return methodInfos
.Where(m => !exclusions.Contains(m.Name) && !m.Name.Contains("<") && m.Name.Contains("_"))
- .Where(m => m.GetParameters().Count() == 0)
- .Where(m => m.ReturnType.ToString() == "System.Void").ToList();
+ .Where(m => m.GetParameters().Length == 0)
+ .Where(m => m.ReturnType == typeof(void)).ToList();
+ }
+
+ public static IEnumerable<Type> GetAbstractBaseClassChainWithClass(this Type type)
+ {
+ var baseClasses = new Stack<Type>();
+
+ for(Type baseClass = type.BaseType;
+ baseClass != null && baseClass.IsAbstract;
+ baseClass = baseClass.BaseType)
+ {
+ baseClasses.Push(baseClass);
+ }
+
+ while (baseClasses.Count > 0) yield return baseClasses.Pop();
+
+ yield return type;
+ }
+
+ public static string CleanName(this Type type)
+ {
+ if (!type.IsGenericType) return type.Name;
+
+ return string.Format("{0}<{1}>", type.Name.Remove(type.Name.IndexOf('`')), string.Join(", ", type.GetGenericArguments().Select(CleanName).ToArray()));
}
public static string CleanMessage(this Exception exception)
@@ -17,6 +17,7 @@ public virtual IEnumerable<Type> SpecClasses()
var leafTypes =
Types.Where(t => t.IsClass
+ && !t.IsAbstract
&& BaseTypes(t).Any(s => s == typeof(nspec))
&& t.Methods().Count() > 0
&& (string.IsNullOrEmpty(filter) || regex.IsMatch(t.FullName)));
@@ -29,7 +30,8 @@ public virtual IEnumerable<Type> SpecClasses()
finalList.AddRange(BaseTypes(leafType));
}
- return finalList.Distinct(new TypeComparer()).Where(s => s != typeof(nspec) && s != typeof(object));
+ return finalList.Distinct(new TypeComparer())
+ .Where(s => s != typeof(nspec) && s != typeof(object) && !s.IsAbstract);
}
public IEnumerable<Type> BaseTypes(Type type)
@@ -50,8 +50,11 @@
<Compile Include="ClassContextBug\NestContextsTests.cs" />
<Compile Include="ClassContextBug\NestedContexts.cs" />
<Compile Include="describe_Conventions.cs" />
+ <Compile Include="describe_RunningSpecs\describe_abstract_class_execution_order.cs" />
+ <Compile Include="describe_RunningSpecs\describe_class_level_before_for_abstract_class.cs" />
<Compile Include="describe_RunningSpecs\describe_Method_Invocation_Sequence.cs" />
<Compile Include="describe_RunningSpecs\describe_LiveFormatter_with_context_filter.cs" />
+ <Compile Include="describe_RunningSpecs\describe_abstract_class_examples.cs" />
<Compile Include="describe_RunningSpecs\describe_example.cs" />
<Compile Include="describe_RunningSpecs\describe_Levels.cs" />
<Compile Include="describe_RunningSpecs\describe_Levels_Inheritance.cs" />
@@ -1,3 +1,5 @@
+using System;
+using System.Collections.Generic;
using System.Linq;
using NSpec;
using NSpec.Domain.Extensions;
@@ -9,19 +11,38 @@ namespace NSpecSpecs
[Category("DomainExtensions")]
public class describe_DomainExtensions
{
- class parent : nspec
+ abstract class indirectAbstractAncestor : nspec
+ {
+ void indirect_ancestor_method() { }
+ }
+
+ class concreteAncestor : indirectAbstractAncestor
+ {
+ void concrete_ancestor_method() { }
+ }
+
+ abstract class abstractAncestor : concreteAncestor
+ {
+ void ancestor_method() { }
+ }
+
+ abstract class abstractParent : abstractAncestor
{
void parent_method() { }
}
- class child : nspec
+ class child : abstractParent
{
public void public_child_method() { }
void private_child_method() { }
void helper_method_with_paramter(int i) { }
void NoUnderscores() { }
}
+ class grandChild : child
+ {
+ }
+
[Test]
public void should_include_direct_private_methods()
{
@@ -37,7 +58,37 @@ public void should_include_direct_public_methods()
[Test]
public void should_disregard_methods_with_out_underscores()
{
- ShouldNotContain("NoUnderscores");
+ ShouldNotContain("NoUnderscores", typeof(child));
+ }
+
+ [Test]
+ public void should_include_methods_from_abstract_parent()
+ {
+ ShouldContain("parent_method");
+ }
+
+ [Test]
+ public void should_include_methods_from_direct_abstract_ancestor()
+ {
+ ShouldContain("ancestor_method");
+ }
+
+ [Test]
+ public void should_disregard_methods_from_concrete_ancestor()
+ {
+ ShouldNotContain("concrete_ancestor_method", typeof(child));
+ }
+
+ [Test]
+ public void should_disregard_methods_from_indirect_abstract_ancestor()
+ {
+ ShouldNotContain("indirect_ancestor_method", typeof(child));
+ }
+
+ [Test]
+ public void should_disregard_methods_from_concrete_parent()
+ {
+ ShouldNotContain("private_child_method", typeof(grandChild));
}
public void ShouldContain(string name)
@@ -47,11 +98,63 @@ public void ShouldContain(string name)
methodInfos.Any(m => m.Name == name).should_be(true);
}
- public void ShouldNotContain(string name)
+ public void ShouldNotContain(string name, Type type)
{
- var methodInfos = typeof(child).Methods();
+ var methodInfos = type.Methods();
methodInfos.Any(m => m.Name == name).should_be(false);
}
+
+ class Foo1{}
+
+ abstract class Foo2 : Foo1{}
+
+ class Foo3 : Foo2{}
+
+ abstract class Foo4 : Foo3{}
+
+ abstract class Foo5 : Foo4{}
+
+ class Foo6 : Foo5{}
+
+ [Test,
+ TestCase(typeof(Foo1), new [] {typeof(Foo1)}),
+ TestCase(typeof(Foo2), new [] {typeof(Foo2)}),
+ TestCase(typeof(Foo3), new [] {typeof(Foo2), typeof(Foo3)}),
+ TestCase(typeof(Foo4), new [] {typeof(Foo4)}),
+ TestCase(typeof(Foo5), new [] {typeof(Foo4), typeof(Foo5)}),
+ TestCase(typeof(Foo6), new [] {typeof(Foo4), typeof(Foo5), typeof(Foo6)})]
+ public void should_build_immediate_abstract_class_chain(Type type, Type[] chain)
+ {
+ IEnumerable<Type> generatedChain = type.GetAbstractBaseClassChainWithClass();
+
+ generatedChain.SequenceEqual(chain).should_be_true();
+ }
+
+ class Bar1{}
+
+ class Bar11 : Bar1{}
+
+ class Bar2<TBaz1>{}
+
+ class Bar21 : Bar2<Bar1>{}
+
+ class Bar3<TBaz1, TBaz2>{}
+
+ class Bar31 : Bar3<Bar1, Bar1>{}
+
+ class Bar32 : Bar3<Bar1, Bar2<Bar1>>{}
+
+ [Test,
+ TestCase(typeof(Bar11), "Bar1"),
+ TestCase(typeof(Bar21), "Bar2<Bar1>"),
+ TestCase(typeof(Bar31), "Bar3<Bar1, Bar1>"),
+ TestCase(typeof(Bar32), "Bar3<Bar1, Bar2<Bar1>>")]
+ public void should_generate_pretty_type_names(Type derivedType, string expectedNameForBaseType)
+ {
+ string name = derivedType.BaseType.CleanName();
+
+ name.should_be(expectedNameForBaseType);
+ }
}
-}
+}
Oops, something went wrong.

0 comments on commit 6ea01c1

Please sign in to comment.