Skip to content

Commit

Permalink
Add book-store exercise (#308)
Browse files Browse the repository at this point in the history
Add book-store exercise test generator
  • Loading branch information
ErikSchierboom authored Jun 29, 2017
1 parent f1c637d commit ca148a7
Show file tree
Hide file tree
Showing 23 changed files with 218 additions and 131 deletions.
2 changes: 1 addition & 1 deletion exercises/book-store/BookStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

public static class BookStore
{
public static double CalculateTotalCost(List<int> books)
public static double Total(IEnumerable<int> books)
{
throw new NotImplementedException("You need to implement this function.");
}
Expand Down
70 changes: 42 additions & 28 deletions exercises/book-store/BookStoreTest.cs
Original file line number Diff line number Diff line change
@@ -1,83 +1,97 @@
using System.Collections.Generic;
using System.Linq;
// This file was auto-generated based on version 1.0.1 of the canonical data.

using Xunit;

public class BookStoreTest
{
[Fact]
public void Basket_with_single_book()
public void Only_a_single_book()
{
Assert.Equal(8, BookStore.CalculateTotalCost(MakeList(1)));
var input = new[] { 1 };
Assert.Equal(8, BookStore.Total(input));
}

[Fact(Skip = "Remove to run test")]
public void Basket_with_two_of_same_book()
public void Two_of_the_same_book()
{
Assert.Equal(16, BookStore.CalculateTotalCost(MakeList(2, 2)));
var input = new[] { 2, 2 };
Assert.Equal(16, BookStore.Total(input));
}

[Fact(Skip = "Remove to run test")]
public void Empty_basket()
{
Assert.Equal(0, BookStore.CalculateTotalCost(MakeList()));
var input = new int[0];
Assert.Equal(0, BookStore.Total(input));
}

[Fact(Skip = "Remove to run test")]
public void Basket_with_two_different_books()
public void Two_different_books()
{
Assert.Equal(15.2, BookStore.CalculateTotalCost(MakeList(1, 2)));
var input = new[] { 1, 2 };
Assert.Equal(15.2, BookStore.Total(input));
}

[Fact(Skip = "Remove to run test")]
public void Basket_with_three_different_books()
public void Three_different_books()
{
Assert.Equal(21.6, BookStore.CalculateTotalCost(MakeList(1, 2, 3)));
var input = new[] { 1, 2, 3 };
Assert.Equal(21.6, BookStore.Total(input));
}

[Fact(Skip = "Remove to run test")]
public void Basket_with_four_different_books()
public void Four_different_books()
{
Assert.Equal(25.6, BookStore.CalculateTotalCost(MakeList(1, 2, 3, 4)));
var input = new[] { 1, 2, 3, 4 };
Assert.Equal(25.6, BookStore.Total(input));
}

[Fact(Skip = "Remove to run test")]
public void Basket_with_five_different_books()
public void Five_different_books()
{
Assert.Equal(30, BookStore.CalculateTotalCost(MakeList(1, 2, 3, 4, 5)));
var input = new[] { 1, 2, 3, 4, 5 };
Assert.Equal(30, BookStore.Total(input));
}

[Fact(Skip = "Remove to run test")]
public void Basket_with_eight_books()
public void Two_groups_of_four_is_cheaper_than_group_of_five_plus_group_of_three()
{
Assert.Equal(51.20, BookStore.CalculateTotalCost(MakeList(1, 1, 2, 2, 3, 3, 4, 5)));
var input = new[] { 1, 1, 2, 2, 3, 3, 4, 5 };
Assert.Equal(51.2, BookStore.Total(input));
}

[Fact(Skip = "Remove to run test")]
public void Basket_with_nine_books()
public void Group_of_four_plus_group_of_two_is_cheaper_than_two_groups_of_three()
{
Assert.Equal(55.60, BookStore.CalculateTotalCost(MakeList(1, 1, 2, 2, 3, 3, 4, 4, 5)));
var input = new[] { 1, 1, 2, 2, 3, 4 };
Assert.Equal(40.8, BookStore.Total(input));
}

[Fact(Skip = "Remove to run test")]
public void Basket_with_ten_books()
public void Two_each_of_first_4_books_and_1_copy_each_of_rest()
{
Assert.Equal(60, BookStore.CalculateTotalCost(MakeList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5)));
var input = new[] { 1, 1, 2, 2, 3, 3, 4, 4, 5 };
Assert.Equal(55.6, BookStore.Total(input));
}

[Fact(Skip = "Remove to run test")]
public void Basket_with_eleven_books()
public void Two_copies_of_each_book()
{
Assert.Equal(68, BookStore.CalculateTotalCost(MakeList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 1)));
var input = new[] { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
Assert.Equal(60, BookStore.Total(input));
}

[Fact(Skip = "Remove to run test")]
public void Basket_with_twelve_books()
public void Three_copies_of_first_book_and_2_each_of_remaining()
{
Assert.Equal(75.20, BookStore.CalculateTotalCost(MakeList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 1, 2)));
var input = new[] { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 1 };
Assert.Equal(68, BookStore.Total(input));
}

private static List<int> MakeList(params int[] values)
[Fact(Skip = "Remove to run test")]
public void Three_each_of_first_2_books_and_2_each_of_remaining_books()
{
return values.ToList();
var input = new[] { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 1, 2 };
Assert.Equal(75.2, BookStore.Total(input));
}
}
}
10 changes: 5 additions & 5 deletions exercises/book-store/Example.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

public static class BookStore
{
public static double CalculateTotalCost(List<int> books)
public static double Total(IEnumerable<int> books)
{
return CalculateTotalCost(books, 0);
return Total(books, 0);
}

private static double CalculateTotalCost(List<int> books, double priceSoFar)
private static double Total(IEnumerable<int> books, double priceSoFar)
{
if (books.Count == 0)
if (!books.Any())
{
return priceSoFar;
}
Expand All @@ -33,7 +33,7 @@ private static double CalculateTotalCost(List<int> books, double priceSoFar)
remaining.Remove(item);
}

var price = CalculateTotalCost(remaining.ToList(), priceSoFar + CostPerGroup(i));
var price = Total(remaining.ToList(), priceSoFar + CostPerGroup(i));
minPrice = Math.Min(minPrice, price);
}

Expand Down
9 changes: 3 additions & 6 deletions exercises/transpose/TransposeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ public void Empty_string()
[Fact(Skip = "Remove to run test")]
public void Two_characters_in_a_row()
{
var input =
"A1";
var input = "A1";
var expected =
"A\n" +
"1";
Expand All @@ -29,8 +28,7 @@ public void Two_characters_in_a_column()
var input =
"A\n" +
"1";
var expected =
"A1";
var expected = "A1";
Assert.Equal(expected, Transpose.String(input));
}

Expand All @@ -50,8 +48,7 @@ public void Simple()
[Fact(Skip = "Remove to run test")]
public void Single_line()
{
var input =
"Single line.";
var input = "Single line.";
var expected =
"S\n" +
"i\n" +
Expand Down
2 changes: 0 additions & 2 deletions generators/Exercise.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ protected Exercise()
{
Name = GetType().ToExerciseName();
CanonicalData = CanonicalDataParser.Parse(Name);
Configuration = new ExerciseConfiguration();
}

public string Name { get; }
public CanonicalData CanonicalData { get; }
public ExerciseConfiguration Configuration { get; }

public void Generate() => TestClassFile.Write(this, Render());

Expand Down
12 changes: 0 additions & 12 deletions generators/ExerciseConfiguration.cs

This file was deleted.

6 changes: 2 additions & 4 deletions generators/Exercises/BeerSong.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
using Generators.Output;

namespace Generators.Exercises
namespace Generators.Exercises
{
public class BeerSong : Exercise
{
public BeerSong()
{
foreach (var canonicalDataCase in CanonicalData.Cases)
canonicalDataCase.Expected = new MultiLineString(canonicalDataCase.Expected.ToString());
canonicalDataCase.UseExpectedParameter = true;
}
}
}
16 changes: 16 additions & 0 deletions generators/Exercises/BookStore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Newtonsoft.Json.Linq;

namespace Generators.Exercises
{
public class BookStore : Exercise
{
public BookStore()
{
foreach (var canonicalDataCase in CanonicalData.Cases)
{
canonicalDataCase.Input = ((JArray)canonicalDataCase.Properties["basket"]).Values<int>();
canonicalDataCase.UseInputParameters = true;
}
}
}
}
8 changes: 5 additions & 3 deletions generators/Exercises/FoodChain.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Generators.Output;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Linq;

namespace Generators.Exercises
{
Expand All @@ -8,7 +7,10 @@ public class FoodChain : Exercise
public FoodChain()
{
foreach (var canonicalDataCase in CanonicalData.Cases)
canonicalDataCase.Expected = new MultiLineString((JArray)canonicalDataCase.Expected);
{
canonicalDataCase.Expected = string.Join("\n", (JArray)canonicalDataCase.Expected);
canonicalDataCase.UseExpectedParameter = true;
}
}
}
}
4 changes: 2 additions & 2 deletions generators/Exercises/NthPrime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ public class NthPrime : Exercise
{
public NthPrime()
{
Configuration.ExceptionType = typeof(ArgumentOutOfRangeException);
Configuration.ThrowExceptionWhenExpectedValueEquals = x => x is bool;
foreach (var canonicalDataCase in CanonicalData.Cases)
canonicalDataCase.ExceptionThrown = canonicalDataCase.Expected is bool ? typeof(ArgumentOutOfRangeException) : null;
}
}
}
16 changes: 6 additions & 10 deletions generators/Exercises/PerfectNumbers.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
using System;
using Generators.Output;
using Humanizer;
using Newtonsoft.Json.Linq;

namespace Generators.Exercises
{
public class PerfectNumbers : Exercise
{
public PerfectNumbers()
{
Configuration.ExceptionType = typeof(ArgumentOutOfRangeException);

foreach (var canonicalDataCase in CanonicalData.Cases)
{
canonicalDataCase.ExceptionThrown = canonicalDataCase.Expected is JObject ? typeof(ArgumentOutOfRangeException) : null;

if (canonicalDataCase.Expected is string classificationType)
canonicalDataCase.Expected = Enum.Parse(typeof(Classification), classificationType, true);
canonicalDataCase.Expected = new UnescapedValue($"Classification.{classificationType.Transform(To.SentenceCase)}");
}
}

private enum Classification
{
Abundant,
Deficient,
Perfect,
}
}
}
3 changes: 1 addition & 2 deletions generators/Exercises/RomanNumerals.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ public class RomanNumerals : Exercise
{
public RomanNumerals()
{
Configuration.TestedMethodType = TestedMethodType.Extension;

foreach (var canonicalDataCase in CanonicalData.Cases)
{
canonicalDataCase.TestedMethodType = TestedMethodType.Extension;
canonicalDataCase.Property = "ToRoman";
canonicalDataCase.Description = "Number_" + canonicalDataCase.Description;
}
Expand Down
7 changes: 4 additions & 3 deletions generators/Exercises/Transpose.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Generators.Output;
using Newtonsoft.Json.Linq;

namespace Generators.Exercises
Expand All @@ -10,8 +9,10 @@ public Transpose()
foreach (var canonicalDataCase in CanonicalData.Cases)
{
canonicalDataCase.Property = "String";
canonicalDataCase.Input = new MultiLineString((JArray)canonicalDataCase.Input);
canonicalDataCase.Expected = new MultiLineString((JArray)canonicalDataCase.Expected);
canonicalDataCase.Input = string.Join("\n", (JArray)canonicalDataCase.Input);
canonicalDataCase.Expected = string.Join("\n", (JArray)canonicalDataCase.Expected);
canonicalDataCase.UseInputParameters = true;
canonicalDataCase.UseExpectedParameter = true;
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions generators/Exercises/Wordy.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
namespace Generators.Exercises
using System;

namespace Generators.Exercises
{
public class Wordy : Exercise
{
public Wordy()
{
Configuration.ThrowExceptionWhenExpectedValueEquals = x => x is bool;
foreach (var canonicalDataCase in CanonicalData.Cases)
canonicalDataCase.ExceptionThrown = canonicalDataCase.Expected is bool ? typeof(ArgumentException) : null;
}
}
}
19 changes: 18 additions & 1 deletion generators/Input/CanonicalDataCase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.ComponentModel.DataAnnotations;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;

namespace Generators.Input
Expand All @@ -16,5 +18,20 @@ public class CanonicalDataCase
public object Input { get; set; }

public object Expected { get; set; }

[JsonIgnore]
public IDictionary<string, object> Properties { get; set; }

[JsonIgnore]
public bool UseInputParameters { get; set; }

[JsonIgnore]
public bool UseExpectedParameter { get; set; }

[JsonIgnore]
public TestedMethodType TestedMethodType { get; set; } = TestedMethodType.Static;

[JsonIgnore]
public Type ExceptionThrown { get; set; }
}
}
Loading

0 comments on commit ca148a7

Please sign in to comment.