From 60928244c092fdb6efab4cbe93289aa32421f45f Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Mon, 20 Mar 2017 12:17:23 +0100 Subject: [PATCH] Add perfect-numbers generator (#253) Restructured generators Support exception-based tests --- exercises/perfect-numbers/Example.cs | 30 +++-- exercises/perfect-numbers/PerfectNumbers.cs | 4 +- .../perfect-numbers/PerfectNumbersTest.cs | 104 +++++++++++++----- generators/{ => Classes}/TestClass.cs | 3 +- .../{ => Classes}/TestClassNameTransformer.cs | 2 +- generators/{ => Classes}/TestClassRenderer.cs | 3 +- .../TestedClassNameTransformer.cs | 2 +- generators/{ => Data}/CanonicalData.cs | 2 +- generators/{ => Data}/CanonicalDataCase.cs | 6 +- .../CanonicalDataCaseJsonConverter.cs | 2 +- .../CanonicalDataCasesJsonConverter.cs | 4 +- generators/{ => Data}/CanonicalDataParser.cs | 10 +- generators/{ => Data}/ExerciseCollection.cs | 6 +- generators/EqualityTestMethodGenerator.cs | 8 -- generators/Exercises/AcronymExercise.cs | 15 ++- generators/Exercises/BooleanExercise.cs | 14 +++ generators/Exercises/EqualityExercise.cs | 14 +++ generators/Exercises/Exercise.cs | 62 ++++++++--- generators/Exercises/LeapExercise.cs | 5 +- .../Exercises/PerfectNumbersExercise.cs | 29 +++++ generators/Exercises/PigLatinExercise.cs | 5 +- generators/{ => Helpers}/StringExtensions.cs | 2 +- generators/{ => Helpers}/To.cs | 5 +- .../BooleanTestMethodGenerator.cs | 6 +- .../Methods/EqualityTestMethodGenerator.cs | 7 ++ .../Methods/ExceptionTestMethodGenerator.cs | 12 ++ generators/{ => Methods}/TestMethod.cs | 5 +- generators/{ => Methods}/TestMethodData.cs | 6 +- .../{ => Methods}/TestMethodGenerator.cs | 30 +++-- .../TestMethodNameTransformer.cs | 2 +- generators/Methods/TestMethodOptions.cs | 12 ++ .../{ => Methods}/TestMethodRenderer.cs | 2 +- .../TestedMethodNameTransformer.cs | 2 +- generators/Program.cs | 2 + 34 files changed, 306 insertions(+), 117 deletions(-) rename generators/{ => Classes}/TestClass.cs (87%) rename generators/{ => Classes}/TestClassNameTransformer.cs (85%) rename generators/{ => Classes}/TestClassRenderer.cs (95%) rename generators/{ => Classes}/TestedClassNameTransformer.cs (85%) rename generators/{ => Data}/CanonicalData.cs (94%) rename generators/{ => Data}/CanonicalDataCase.cs (85%) rename generators/{ => Data}/CanonicalDataCaseJsonConverter.cs (97%) rename generators/{ => Data}/CanonicalDataCasesJsonConverter.cs (97%) rename generators/{ => Data}/CanonicalDataParser.cs (80%) rename generators/{ => Data}/ExerciseCollection.cs (90%) delete mode 100644 generators/EqualityTestMethodGenerator.cs create mode 100644 generators/Exercises/BooleanExercise.cs create mode 100644 generators/Exercises/EqualityExercise.cs create mode 100644 generators/Exercises/PerfectNumbersExercise.cs rename generators/{ => Helpers}/StringExtensions.cs (86%) rename generators/{ => Helpers}/To.cs (84%) rename generators/{ => Methods}/BooleanTestMethodGenerator.cs (67%) create mode 100644 generators/Methods/EqualityTestMethodGenerator.cs create mode 100644 generators/Methods/ExceptionTestMethodGenerator.cs rename generators/{ => Methods}/TestMethod.cs (53%) rename generators/{ => Methods}/TestMethodData.cs (61%) rename generators/{ => Methods}/TestMethodGenerator.cs (58%) rename generators/{ => Methods}/TestMethodNameTransformer.cs (91%) create mode 100644 generators/Methods/TestMethodOptions.cs rename generators/{ => Methods}/TestMethodRenderer.cs (93%) rename generators/{ => Methods}/TestedMethodNameTransformer.cs (85%) diff --git a/exercises/perfect-numbers/Example.cs b/exercises/perfect-numbers/Example.cs index cabcc4fc80..f5ae6f38a5 100644 --- a/exercises/perfect-numbers/Example.cs +++ b/exercises/perfect-numbers/Example.cs @@ -1,35 +1,33 @@ -public enum NumberType +using System; + +public enum Classification { Perfect, Abundant, Deficient } -public class PerfectNumbers +public static class PerfectNumbers { - public static NumberType Classify(int number) + public static Classification Classify(int number) { + if (number < 1) + throw new ArgumentOutOfRangeException(); + int sumOfFactors = 0; for (int i = 1; i < number; i++) { if (number % i == 0) - { sumOfFactors += i; - } } if (sumOfFactors < number) - { - return NumberType.Deficient; - } - else if (sumOfFactors == number) - { - return NumberType.Perfect; - } - else - { - return NumberType.Abundant; - } + return Classification.Deficient; + + if (sumOfFactors == number) + return Classification.Perfect; + + return Classification.Abundant; } } diff --git a/exercises/perfect-numbers/PerfectNumbers.cs b/exercises/perfect-numbers/PerfectNumbers.cs index 479af7d024..936d79e13f 100644 --- a/exercises/perfect-numbers/PerfectNumbers.cs +++ b/exercises/perfect-numbers/PerfectNumbers.cs @@ -1,6 +1,6 @@ using System; -public enum NumberType +public enum Classification { Perfect, Abundant, @@ -9,7 +9,7 @@ public enum NumberType public static class PerfectNumbers { - public static NumberType Classify(int number) + public static Classification Classify(int number) { throw new NotImplementedException(); } diff --git a/exercises/perfect-numbers/PerfectNumbersTest.cs b/exercises/perfect-numbers/PerfectNumbersTest.cs index 3e458bec23..60ff732ffe 100644 --- a/exercises/perfect-numbers/PerfectNumbersTest.cs +++ b/exercises/perfect-numbers/PerfectNumbersTest.cs @@ -1,31 +1,83 @@ -using Xunit; +using Xunit; +using System; public class PerfectNumbersTest { - [Theory] - [InlineData(3)] - [InlineData(7)] - [InlineData(13)] - public void Can_classify_deficient_numbers(int number) - { - Assert.Equal(NumberType.Deficient, PerfectNumbers.Classify(number)); - } - - [Theory(Skip = "Remove to run test")] - [InlineData(6)] - [InlineData(28)] - [InlineData(496)] - public void Can_classify_perfect_numbers(int number) - { - Assert.Equal(NumberType.Perfect, PerfectNumbers.Classify(number)); - } - - [Theory(Skip = "Remove to run test")] - [InlineData(12)] - [InlineData(18)] - [InlineData(20)] - public void Can_classify_abundant_numbers(int number) - { - Assert.Equal(NumberType.Abundant, PerfectNumbers.Classify(number)); + [Fact] + public void Smallest_perfect_number_is_classified_correctly() + { + Assert.Equal(Classification.Perfect, PerfectNumbers.Classify(6)); + } + + [Fact(Skip = "Remove to run test")] + public void Medium_perfect_number_is_classified_correctly() + { + Assert.Equal(Classification.Perfect, PerfectNumbers.Classify(28)); + } + + [Fact(Skip = "Remove to run test")] + public void Large_perfect_number_is_classified_correctly() + { + Assert.Equal(Classification.Perfect, PerfectNumbers.Classify(33550336)); + } + + [Fact(Skip = "Remove to run test")] + public void Smallest_abundant_number_is_classified_correctly() + { + Assert.Equal(Classification.Abundant, PerfectNumbers.Classify(12)); + } + + [Fact(Skip = "Remove to run test")] + public void Medium_abundant_number_is_classified_correctly() + { + Assert.Equal(Classification.Abundant, PerfectNumbers.Classify(30)); + } + + [Fact(Skip = "Remove to run test")] + public void Large_abundant_number_is_classified_correctly() + { + Assert.Equal(Classification.Abundant, PerfectNumbers.Classify(33550335)); + } + + [Fact(Skip = "Remove to run test")] + public void Smallest_prime_deficient_number_is_classified_correctly() + { + Assert.Equal(Classification.Deficient, PerfectNumbers.Classify(2)); + } + + [Fact(Skip = "Remove to run test")] + public void Smallest_non_prime_deficient_number_is_classified_correctly() + { + Assert.Equal(Classification.Deficient, PerfectNumbers.Classify(4)); + } + + [Fact(Skip = "Remove to run test")] + public void Medium_deficient_number_is_classified_correctly() + { + Assert.Equal(Classification.Deficient, PerfectNumbers.Classify(32)); + } + + [Fact(Skip = "Remove to run test")] + public void Large_deficient_number_is_classified_correctly() + { + Assert.Equal(Classification.Deficient, PerfectNumbers.Classify(33550337)); + } + + [Fact(Skip = "Remove to run test")] + public void Edge_case_no_factors_other_than_itself_is_classified_correctly() + { + Assert.Equal(Classification.Deficient, PerfectNumbers.Classify(1)); + } + + [Fact(Skip = "Remove to run test")] + public void Zero_is_rejected_not_a_natural_number_() + { + Assert.Throws(() => PerfectNumbers.Classify(0)); + } + + [Fact(Skip = "Remove to run test")] + public void Negative_integer_is_rejected_not_a_natural_number_() + { + Assert.Throws(() => PerfectNumbers.Classify(-1)); } } \ No newline at end of file diff --git a/generators/TestClass.cs b/generators/Classes/TestClass.cs similarity index 87% rename from generators/TestClass.cs rename to generators/Classes/TestClass.cs index ee71e89a36..281d4eb625 100644 --- a/generators/TestClass.cs +++ b/generators/Classes/TestClass.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; +using Generators.Methods; -namespace Generators +namespace Generators.Classes { public class TestClass { diff --git a/generators/TestClassNameTransformer.cs b/generators/Classes/TestClassNameTransformer.cs similarity index 85% rename from generators/TestClassNameTransformer.cs rename to generators/Classes/TestClassNameTransformer.cs index 505d147c50..d6f69e61b4 100644 --- a/generators/TestClassNameTransformer.cs +++ b/generators/Classes/TestClassNameTransformer.cs @@ -1,6 +1,6 @@ using Humanizer; -namespace Generators +namespace Generators.Classes { public class TestClassNameTransformer : IStringTransformer { diff --git a/generators/TestClassRenderer.cs b/generators/Classes/TestClassRenderer.cs similarity index 95% rename from generators/TestClassRenderer.cs rename to generators/Classes/TestClassRenderer.cs index d6a948a2bf..82b2260724 100644 --- a/generators/TestClassRenderer.cs +++ b/generators/Classes/TestClassRenderer.cs @@ -1,7 +1,8 @@ using System.Collections.Generic; using System.Linq; +using Generators.Methods; -namespace Generators +namespace Generators.Classes { public static class TestClassRenderer { diff --git a/generators/TestedClassNameTransformer.cs b/generators/Classes/TestedClassNameTransformer.cs similarity index 85% rename from generators/TestedClassNameTransformer.cs rename to generators/Classes/TestedClassNameTransformer.cs index 0f9ab59768..3d12c3a30e 100644 --- a/generators/TestedClassNameTransformer.cs +++ b/generators/Classes/TestedClassNameTransformer.cs @@ -1,6 +1,6 @@ using Humanizer; -namespace Generators +namespace Generators.Classes { public class TestedClassNameTransformer : IStringTransformer { diff --git a/generators/CanonicalData.cs b/generators/Data/CanonicalData.cs similarity index 94% rename from generators/CanonicalData.cs rename to generators/Data/CanonicalData.cs index 367c04862a..577c96871e 100644 --- a/generators/CanonicalData.cs +++ b/generators/Data/CanonicalData.cs @@ -1,7 +1,7 @@ using System.ComponentModel.DataAnnotations; using Newtonsoft.Json; -namespace Generators +namespace Generators.Data { public class CanonicalData { diff --git a/generators/CanonicalDataCase.cs b/generators/Data/CanonicalDataCase.cs similarity index 85% rename from generators/CanonicalDataCase.cs rename to generators/Data/CanonicalDataCase.cs index 7ece6aaef7..081b535f61 100644 --- a/generators/CanonicalDataCase.cs +++ b/generators/Data/CanonicalDataCase.cs @@ -1,8 +1,8 @@ -using Newtonsoft.Json; -using System.Collections.Generic; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using Newtonsoft.Json; -namespace Generators +namespace Generators.Data { [JsonConverter(typeof(CanonicalDataCaseJsonConverter))] public class CanonicalDataCase diff --git a/generators/CanonicalDataCaseJsonConverter.cs b/generators/Data/CanonicalDataCaseJsonConverter.cs similarity index 97% rename from generators/CanonicalDataCaseJsonConverter.cs rename to generators/Data/CanonicalDataCaseJsonConverter.cs index 7fa7b31600..c1003e25e8 100644 --- a/generators/CanonicalDataCaseJsonConverter.cs +++ b/generators/Data/CanonicalDataCaseJsonConverter.cs @@ -3,7 +3,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -namespace Generators +namespace Generators.Data { public class CanonicalDataCaseJsonConverter : JsonConverter { diff --git a/generators/CanonicalDataCasesJsonConverter.cs b/generators/Data/CanonicalDataCasesJsonConverter.cs similarity index 97% rename from generators/CanonicalDataCasesJsonConverter.cs rename to generators/Data/CanonicalDataCasesJsonConverter.cs index 05b0fc7596..9092376425 100644 --- a/generators/CanonicalDataCasesJsonConverter.cs +++ b/generators/Data/CanonicalDataCasesJsonConverter.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using System.Linq; -namespace Generators +namespace Generators.Data { public class CanonicalDataCasesJsonConverter : JsonConverter { diff --git a/generators/CanonicalDataParser.cs b/generators/Data/CanonicalDataParser.cs similarity index 80% rename from generators/CanonicalDataParser.cs rename to generators/Data/CanonicalDataParser.cs index 130d505368..d804eacaeb 100644 --- a/generators/CanonicalDataParser.cs +++ b/generators/Data/CanonicalDataParser.cs @@ -1,13 +1,13 @@ -using Newtonsoft.Json; -using System; +using System; using System.ComponentModel.DataAnnotations; using System.Net.Http; +using Newtonsoft.Json; -namespace Generators +namespace Generators.Data { public static class CanonicalDataParser { - private static readonly HttpClient httpClient = new HttpClient(); + private static readonly HttpClient HttpClient = new HttpClient(); public static CanonicalData Parse(string exercise) { @@ -20,7 +20,7 @@ public static CanonicalData Parse(string exercise) } private static string DownloadCanonicalDataJson(string exercise) - => httpClient.GetStringAsync(GetCanonicalDataUrl(exercise)).GetAwaiter().GetResult(); + => HttpClient.GetStringAsync(GetCanonicalDataUrl(exercise)).GetAwaiter().GetResult(); private static Uri GetCanonicalDataUrl(string exercise) => new Uri($"https://raw.githubusercontent.com/exercism/x-common/master/exercises/{exercise}/canonical-data.json"); diff --git a/generators/ExerciseCollection.cs b/generators/Data/ExerciseCollection.cs similarity index 90% rename from generators/ExerciseCollection.cs rename to generators/Data/ExerciseCollection.cs index ded5636a85..db96ec628f 100644 --- a/generators/ExerciseCollection.cs +++ b/generators/Data/ExerciseCollection.cs @@ -1,11 +1,11 @@ -using Generators.Exercises; -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; +using Generators.Exercises; -namespace Generators +namespace Generators.Data { public class ExerciseCollection : IEnumerable { diff --git a/generators/EqualityTestMethodGenerator.cs b/generators/EqualityTestMethodGenerator.cs deleted file mode 100644 index 7508b2e254..0000000000 --- a/generators/EqualityTestMethodGenerator.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Generators -{ - public class EqualityTestMethodGenerator : TestMethodGenerator - { - protected override string GetBody() - => $"Assert.Equal({Expected}, {TestedClassName}.{TestedMethod}({Input}));"; - } -} \ No newline at end of file diff --git a/generators/Exercises/AcronymExercise.cs b/generators/Exercises/AcronymExercise.cs index 13c6878a21..d7a6654022 100644 --- a/generators/Exercises/AcronymExercise.cs +++ b/generators/Exercises/AcronymExercise.cs @@ -1,15 +1,20 @@ -namespace Generators.Exercises +using Generators.Data; +using Generators.Methods; + +namespace Generators.Exercises { - public class AcronymExercise : Exercise + public class AcronymExercise : EqualityExercise { public AcronymExercise() : base("acronym") { } - protected override TestMethod CreateTestMethod(TestMethodData testMethodData) + protected override TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) { - testMethodData.InputProperty = "phrase"; - return CreateEqualityTestMethod(testMethodData); + var testMethodData = base.CreateTestMethodData(canonicalData, canonicalDataCase, index); + testMethodData.Options.InputProperty = "phrase"; + + return testMethodData; } } } \ No newline at end of file diff --git a/generators/Exercises/BooleanExercise.cs b/generators/Exercises/BooleanExercise.cs new file mode 100644 index 0000000000..afc9d87d71 --- /dev/null +++ b/generators/Exercises/BooleanExercise.cs @@ -0,0 +1,14 @@ +using Generators.Methods; + +namespace Generators.Exercises +{ + public abstract class BooleanExercise : Exercise + { + protected BooleanExercise(string name) : base(name) + { + } + + protected override TestMethod CreateTestMethod(TestMethodData testMethodData) + => CreateBooleanTestMethod(testMethodData); + } +} \ No newline at end of file diff --git a/generators/Exercises/EqualityExercise.cs b/generators/Exercises/EqualityExercise.cs new file mode 100644 index 0000000000..0e212c3e27 --- /dev/null +++ b/generators/Exercises/EqualityExercise.cs @@ -0,0 +1,14 @@ +using Generators.Methods; + +namespace Generators.Exercises +{ + public abstract class EqualityExercise : Exercise + { + protected EqualityExercise(string name) : base(name) + { + } + + protected override TestMethod CreateTestMethod(TestMethodData testMethodData) + => CreateEqualityTestMethod(testMethodData); + } +} \ No newline at end of file diff --git a/generators/Exercises/Exercise.cs b/generators/Exercises/Exercise.cs index b9318f2cdc..1bb6938c22 100644 --- a/generators/Exercises/Exercise.cs +++ b/generators/Exercises/Exercise.cs @@ -1,6 +1,11 @@ using System.Collections.Generic; using System.Linq; +using Generators.Classes; +using Generators.Data; +using Generators.Methods; using Humanizer; +using Newtonsoft.Json.Linq; +using To = Generators.Helpers.To; namespace Generators.Exercises { @@ -8,6 +13,7 @@ public abstract class Exercise { private static readonly BooleanTestMethodGenerator BooleanTestMethodGenerator = new BooleanTestMethodGenerator(); private static readonly EqualityTestMethodGenerator EqualityTestMethodGenerator = new EqualityTestMethodGenerator(); + private static readonly ExceptionTestMethodGenerator ExceptionTestMethodGenerator = new ExceptionTestMethodGenerator(); protected Exercise(string name) { @@ -16,25 +22,55 @@ protected Exercise(string name) public string Name { get; } - public TestClass CreateTestClass(CanonicalData canonicalData) => new TestClass + public TestClass CreateTestClass(CanonicalData canonicalData) { - ClassName = Name.Transform(To.TestClassName), - TestMethods = CreateTestMethods(canonicalData).ToArray() - }; + var testClass = new TestClass + { + ClassName = Name.Transform(To.TestClassName), + TestMethods = CreateTestMethods(canonicalData).ToArray() + }; + + AddTestMethodUsingNamespaces(testClass); + + return testClass; + } + + private static void AddTestMethodUsingNamespaces(TestClass testClass) + { + foreach (var testMethod in testClass.TestMethods) + testClass.UsingNamespaces.UnionWith(testMethod.UsingNamespaces); + } + + protected abstract TestMethod CreateTestMethod(TestMethodData testMethodData); + + protected virtual IEnumerable CreateTestMethods(CanonicalData canonicalData) + => canonicalData.Cases.Select((t, i) => CreateTestMethod(canonicalData, t, i)); - private IEnumerable CreateTestMethods(CanonicalData canonicalData) - => canonicalData.Cases.Select((canonicalDataCase, index) => CreateTestMethod(new TestMethodData - { - CanonicalData = canonicalData, - CanonicalDataCase = canonicalDataCase, + protected virtual TestMethod CreateTestMethod(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) + { + var testMethodData = CreateTestMethodData(canonicalData, canonicalDataCase, index); + + if (testMethodData.CanonicalDataCase.Expected is JObject jObject) + return CreateExceptionTestMethod(testMethodData); + + return CreateTestMethod(testMethodData); + } + + protected virtual TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) + => new TestMethodData + { + CanonicalData = canonicalData, + CanonicalDataCase = canonicalDataCase, Index = index - })); - protected abstract TestMethod CreateTestMethod(TestMethodData testMethodData); + }; - protected TestMethod CreateBooleanTestMethod(TestMethodData testMethodData) + protected virtual TestMethod CreateBooleanTestMethod(TestMethodData testMethodData) => BooleanTestMethodGenerator.Create(testMethodData); - protected TestMethod CreateEqualityTestMethod(TestMethodData testMethodData) + protected virtual TestMethod CreateEqualityTestMethod(TestMethodData testMethodData) => EqualityTestMethodGenerator.Create(testMethodData); + + protected virtual TestMethod CreateExceptionTestMethod(TestMethodData testMethodData) + => ExceptionTestMethodGenerator.Create(testMethodData); } } \ No newline at end of file diff --git a/generators/Exercises/LeapExercise.cs b/generators/Exercises/LeapExercise.cs index 14f0e7f04a..b3689f4f7e 100644 --- a/generators/Exercises/LeapExercise.cs +++ b/generators/Exercises/LeapExercise.cs @@ -1,12 +1,9 @@ namespace Generators.Exercises { - public class LeapExercise : Exercise + public class LeapExercise : BooleanExercise { public LeapExercise() : base("leap") { } - - protected override TestMethod CreateTestMethod(TestMethodData testMethodData) - => CreateBooleanTestMethod(testMethodData); } } \ No newline at end of file diff --git a/generators/Exercises/PerfectNumbersExercise.cs b/generators/Exercises/PerfectNumbersExercise.cs new file mode 100644 index 0000000000..ba84988a81 --- /dev/null +++ b/generators/Exercises/PerfectNumbersExercise.cs @@ -0,0 +1,29 @@ +using System; +using Generators.Data; +using Generators.Methods; +using Humanizer; + +namespace Generators.Exercises +{ + public class PerfectNumbersExercise : EqualityExercise + { + public PerfectNumbersExercise() : base("perfect-numbers") + { + } + + protected override TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) + { + var testMethodData = base.CreateTestMethodData(canonicalData, canonicalDataCase, index); + testMethodData.Options.ExceptionType = typeof(ArgumentOutOfRangeException); + testMethodData.Options.FormatExpected = false; + + if (testMethodData.CanonicalDataCase.Expected is string classificationType) + testMethodData.CanonicalDataCase.Expected = GetClassification(classificationType); + + return testMethodData; + } + + private static string GetClassification(string classificationType) + => $"Classification.{classificationType.Transform(Humanizer.To.TitleCase)}"; + } +} \ No newline at end of file diff --git a/generators/Exercises/PigLatinExercise.cs b/generators/Exercises/PigLatinExercise.cs index c939234565..7241affc9e 100644 --- a/generators/Exercises/PigLatinExercise.cs +++ b/generators/Exercises/PigLatinExercise.cs @@ -1,12 +1,9 @@ namespace Generators.Exercises { - public class PigLatinExercise : Exercise + public class PigLatinExercise : EqualityExercise { public PigLatinExercise() : base("pig-latin") { } - - protected override TestMethod CreateTestMethod(TestMethodData testMethodData) - => CreateEqualityTestMethod(testMethodData); } } \ No newline at end of file diff --git a/generators/StringExtensions.cs b/generators/Helpers/StringExtensions.cs similarity index 86% rename from generators/StringExtensions.cs rename to generators/Helpers/StringExtensions.cs index b4d20a82b6..b949f3186f 100644 --- a/generators/StringExtensions.cs +++ b/generators/Helpers/StringExtensions.cs @@ -1,4 +1,4 @@ -namespace Generators +namespace Generators.Helpers { public static class StringExtensions { diff --git a/generators/To.cs b/generators/Helpers/To.cs similarity index 84% rename from generators/To.cs rename to generators/Helpers/To.cs index a1909cf8f2..b1a03ca62e 100644 --- a/generators/To.cs +++ b/generators/Helpers/To.cs @@ -1,4 +1,7 @@ -namespace Generators +using Generators.Classes; +using Generators.Methods; + +namespace Generators.Helpers { public static class To { diff --git a/generators/BooleanTestMethodGenerator.cs b/generators/Methods/BooleanTestMethodGenerator.cs similarity index 67% rename from generators/BooleanTestMethodGenerator.cs rename to generators/Methods/BooleanTestMethodGenerator.cs index 5ade13017c..8b4ee2a097 100644 --- a/generators/BooleanTestMethodGenerator.cs +++ b/generators/Methods/BooleanTestMethodGenerator.cs @@ -1,11 +1,11 @@ using System; +using Generators.Helpers; -namespace Generators +namespace Generators.Methods { public class BooleanTestMethodGenerator : TestMethodGenerator { - protected override string GetBody() - => $"{Assertion}({TestedClassName}.{TestedMethod}({Input}));"; + protected override string Body => $"{Assertion}({TestedClassName}.{TestedMethod}({Input}));"; private string Assertion => $"Assert.{Convert.ToBoolean(TestMethodData.CanonicalDataCase.Expected)}"; diff --git a/generators/Methods/EqualityTestMethodGenerator.cs b/generators/Methods/EqualityTestMethodGenerator.cs new file mode 100644 index 0000000000..93d284bfd1 --- /dev/null +++ b/generators/Methods/EqualityTestMethodGenerator.cs @@ -0,0 +1,7 @@ +namespace Generators.Methods +{ + public class EqualityTestMethodGenerator : TestMethodGenerator + { + protected override string Body => $"Assert.Equal({Expected}, {TestedClassName}.{TestedMethod}({Input}));"; + } +} \ No newline at end of file diff --git a/generators/Methods/ExceptionTestMethodGenerator.cs b/generators/Methods/ExceptionTestMethodGenerator.cs new file mode 100644 index 0000000000..b5f1d78e71 --- /dev/null +++ b/generators/Methods/ExceptionTestMethodGenerator.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace Generators.Methods +{ + public class ExceptionTestMethodGenerator : TestMethodGenerator + { + protected override string Body + => $"Assert.Throws<{TestMethodData.Options.ExceptionType.Name}>(() => {TestedClassName}.{TestedMethod}({Input}));"; + + protected override ISet UsingNamespaces => new HashSet { TestMethodData.Options.ExceptionType.Namespace }; + } +} \ No newline at end of file diff --git a/generators/TestMethod.cs b/generators/Methods/TestMethod.cs similarity index 53% rename from generators/TestMethod.cs rename to generators/Methods/TestMethod.cs index 99cfc89b8b..ae87a55301 100644 --- a/generators/TestMethod.cs +++ b/generators/Methods/TestMethod.cs @@ -1,7 +1,10 @@ -namespace Generators +using System.Collections.Generic; + +namespace Generators.Methods { public class TestMethod { + public ISet UsingNamespaces { get; set; } = new HashSet(); public string MethodName { get; set; } public string Body { get; set; } public int Index { get; set; } diff --git a/generators/TestMethodData.cs b/generators/Methods/TestMethodData.cs similarity index 61% rename from generators/TestMethodData.cs rename to generators/Methods/TestMethodData.cs index 03b9705b67..fbbe591dbc 100644 --- a/generators/TestMethodData.cs +++ b/generators/Methods/TestMethodData.cs @@ -1,10 +1,12 @@ -namespace Generators +using Generators.Data; + +namespace Generators.Methods { public class TestMethodData { public CanonicalData CanonicalData { get; set; } public CanonicalDataCase CanonicalDataCase { get; set;} public int Index { get; set; } - public string InputProperty { get; set; } + public TestMethodOptions Options { get; } = new TestMethodOptions(); } } \ No newline at end of file diff --git a/generators/TestMethodGenerator.cs b/generators/Methods/TestMethodGenerator.cs similarity index 58% rename from generators/TestMethodGenerator.cs rename to generators/Methods/TestMethodGenerator.cs index b714785a9b..da669c7e5f 100644 --- a/generators/TestMethodGenerator.cs +++ b/generators/Methods/TestMethodGenerator.cs @@ -1,6 +1,8 @@ -using Humanizer; +using System.Collections.Generic; +using Humanizer; +using To = Generators.Helpers.To; -namespace Generators +namespace Generators.Methods { public abstract class TestMethodGenerator { @@ -11,14 +13,18 @@ public TestMethod Create(TestMethodData testMethodData) return new TestMethod { MethodName = MethodName, - Body = GetBody(), - Index = TestMethodData.Index + Body = Body, + Index = TestMethodData.Index, + UsingNamespaces = UsingNamespaces }; } protected TestMethodData TestMethodData { get; private set; } - protected abstract string GetBody(); + protected abstract string Body { get; } + + protected virtual ISet UsingNamespaces + => new HashSet(); protected virtual string MethodName => TestMethodData.CanonicalDataCase.Description.Replace(":", " is").Transform(To.TestMethodName); @@ -29,14 +35,20 @@ protected virtual string TestedClassName protected virtual string TestedMethod => TestMethodData.CanonicalDataCase.Property.Transform(To.TestedMethodName); - protected virtual object Input => FormatValue(InputValue); + protected virtual object Input => + TestMethodData.Options.FormatInput + ? FormatValue(InputValue) + : InputValue; - protected virtual object Expected => FormatValue(TestMethodData.CanonicalDataCase.Expected); + protected virtual object Expected => + TestMethodData.Options.FormatExpected + ? FormatValue(TestMethodData.CanonicalDataCase.Expected) + : TestMethodData.CanonicalDataCase.Expected; protected virtual object InputValue - => TestMethodData.InputProperty == null + => TestMethodData.Options.InputProperty == null ? TestMethodData.CanonicalDataCase.Input - : TestMethodData.CanonicalDataCase.Data[TestMethodData.InputProperty]; + : TestMethodData.CanonicalDataCase.Data[TestMethodData.Options.InputProperty]; protected virtual object FormatValue(object val) { diff --git a/generators/TestMethodNameTransformer.cs b/generators/Methods/TestMethodNameTransformer.cs similarity index 91% rename from generators/TestMethodNameTransformer.cs rename to generators/Methods/TestMethodNameTransformer.cs index 15115f6e82..d7ebc42b3d 100644 --- a/generators/TestMethodNameTransformer.cs +++ b/generators/Methods/TestMethodNameTransformer.cs @@ -1,7 +1,7 @@ using System.Text.RegularExpressions; using Humanizer; -namespace Generators +namespace Generators.Methods { public class TestMethodNameTransformer : IStringTransformer { diff --git a/generators/Methods/TestMethodOptions.cs b/generators/Methods/TestMethodOptions.cs new file mode 100644 index 0000000000..532ae1352b --- /dev/null +++ b/generators/Methods/TestMethodOptions.cs @@ -0,0 +1,12 @@ +using System; + +namespace Generators.Methods +{ + public class TestMethodOptions + { + public string InputProperty { get; set; } + public bool FormatInput { get; set; } = true; + public bool FormatExpected { get; set; } = true; + public Type ExceptionType { get; set; } = typeof(ArgumentException); + } +} \ No newline at end of file diff --git a/generators/TestMethodRenderer.cs b/generators/Methods/TestMethodRenderer.cs similarity index 93% rename from generators/TestMethodRenderer.cs rename to generators/Methods/TestMethodRenderer.cs index ce941e5920..d0343e82cf 100644 --- a/generators/TestMethodRenderer.cs +++ b/generators/Methods/TestMethodRenderer.cs @@ -1,4 +1,4 @@ -namespace Generators +namespace Generators.Methods { public static class TestMethodRenderer { diff --git a/generators/TestedMethodNameTransformer.cs b/generators/Methods/TestedMethodNameTransformer.cs similarity index 85% rename from generators/TestedMethodNameTransformer.cs rename to generators/Methods/TestedMethodNameTransformer.cs index 75574780ff..1417d33b52 100644 --- a/generators/TestedMethodNameTransformer.cs +++ b/generators/Methods/TestedMethodNameTransformer.cs @@ -1,6 +1,6 @@ using Humanizer; -namespace Generators +namespace Generators.Methods { public class TestedMethodNameTransformer : IStringTransformer { diff --git a/generators/Program.cs b/generators/Program.cs index 200e6f7bdd..f4355c56fd 100644 --- a/generators/Program.cs +++ b/generators/Program.cs @@ -1,5 +1,7 @@ using Generators.Exercises; using System.IO; +using Generators.Classes; +using Generators.Data; using Serilog; namespace Generators