├── language.yml
├── rider-settings
└── settings.zip
├── .gitignore
├── src
├── Kata
│ ├── Kata.csproj
│ └── Monkey.cs
├── Kata.Spec
│ ├── CommandDispatch
│ │ └── when_dispatching_a_command.cs
│ ├── StringCalc
│ │ └── when_feeding_the_monkey.cs
│ ├── Kata.Spec.csproj
│ └── BuildingEntry
│ │ └── when_monitoring_an_entrance.cs
└── Kata-Starter.sln
├── templates
├── readme.md
├── spec.cs
└── sadspec.cs
├── README.md
└── katas
├── string_calculator.md
└── parking_lot.md
/language.yml:
--------------------------------------------------------------------------------
1 | image: gitpod/workspace-dotnet
2 | vscode:
3 | extensions:
4 | - muhammad-sammy.csharp
5 |
--------------------------------------------------------------------------------
/rider-settings/settings.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bsommardahl/oreilly-kata-starter/HEAD/rider-settings/settings.zip
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | obj/
2 | [Bb]in
3 | [Dd]ebug*/
4 | [Rr]elease*/
5 |
6 | #Tooling
7 | _ReSharper*/
8 | *.resharper
9 | *.DotSettings
10 | *.DotSettings.*
11 | [Tt]est[Rr]esult*
12 | .idea/
13 |
14 | node_modules
--------------------------------------------------------------------------------
/src/Kata/Kata.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | latest
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/templates/readme.md:
--------------------------------------------------------------------------------
1 | # Templates
2 |
3 | Adding live templates to rider is easy! Check out this link for instructions: https://www.jetbrains.com/help/rider/Creating_and_Editing_Live_Templates.html
4 |
5 | - [spec](spec.cs)
6 | - [sadspec](sadspec.cs)
7 |
8 | The order of steps should be:
9 | - spec_name
10 | - do_something
11 | - sut
12 |
--------------------------------------------------------------------------------
/templates/spec.cs:
--------------------------------------------------------------------------------
1 | public class when_$spec_name$
2 | {
3 | Establish _context = () => { _systemUnderTest = new $sut$ };
4 |
5 | Because of = () => { _result = _systemUnderTest.Action(); };
6 |
7 | It should_$do_something$ = () =>
8 | {
9 | _result.Should().Be(something);
10 | };
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/templates/sadspec.cs:
--------------------------------------------------------------------------------
1 | public class when_$spec_name$
2 | {
3 | Establish _context = () => { _systemUnderTest = new $sut$ };
4 |
5 | Because of = () => { _result = Catch.Exception(()=> _systemUnderTest.Action()); };
6 |
7 | It should_$do_something$ = () =>
8 | {
9 | _result.Message.Should().Be(something);
10 | };
11 | static Exception _result;
12 | }
13 |
--------------------------------------------------------------------------------
/src/Kata/Monkey.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 |
4 | namespace Kata
5 | {
6 | public class Monkey
7 | {
8 | public Monkey()
9 | {
10 | Belly = new List();
11 | }
12 |
13 | public IList Belly { get; }
14 |
15 | public void Eat(string food)
16 | {
17 | Belly.Add(food);
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/Kata.Spec/CommandDispatch/when_dispatching_a_command.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using FluentAssertions;
4 | using Machine.Specifications;
5 | using Moq;
6 | using It = Machine.Specifications.It;
7 |
8 | namespace Kata.Spec.CommandDispatch
9 | {
10 | //
11 | //Create a dispatcher that can match commands with handlers and execute them.
12 | //
13 | // v1 - Name matching and hand-coded test object
14 | // v2 - CanHandle method and mocked handler
15 | }
--------------------------------------------------------------------------------
/src/Kata.Spec/StringCalc/when_feeding_the_monkey.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using FluentAssertions;
3 | using Machine.Specifications;
4 |
5 | namespace Kata.Spec.StringCalc
6 | {
7 | public class when_feeding_the_monkey
8 | {
9 | static Monkey _systemUnderTest;
10 |
11 | Establish context = () =>
12 | _systemUnderTest = new Monkey();
13 |
14 | Because of = () =>
15 | _systemUnderTest.Eat("banana");
16 |
17 | It should_have_the_food_in_its_belly = () =>
18 | _systemUnderTest.Belly.Should().Contain("banana");
19 | }
20 | }
--------------------------------------------------------------------------------
/src/Kata.Spec/Kata.Spec.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | latest
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/Kata.Spec/BuildingEntry/when_monitoring_an_entrance.cs:
--------------------------------------------------------------------------------
1 | using Machine.Specifications;
2 |
3 | namespace Kata.Spec.BuildingEntry
4 | {
5 | // public class when_monitoring_an_entrance
6 | // {
7 | // Establish _context = () =>
8 | // {
9 | // _systemUnderTest = new EntranceMonitor();
10 | // };
11 | //
12 | // Because of = () => { _result = _systemUnderTest.Entrance("123"); };
13 | //
14 | // It should_log_the_entrance_to_the_db = () => { _result.Should().Be(something); };
15 | // }
16 |
17 | // Entrance Monitor Kata
18 | // Build a class that can receive info about a badge-in entrance event and react appropriately
19 |
20 | // 1. Log entrance into building to the db including badgeId and dateTime
21 | // 2. Solve "entrance" instantiation problem with Factory (refactor)
22 | // 3. Verify badge Id access based on badge type (implement strategy)
23 | // 4. Notify security on unauthorized access
24 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to the Kata Starter
2 |
3 | ### For Best Results
4 |
5 | 1) Install Jetbrains Rider 2019.3.1 (free evaluation).
6 |
7 | 2) Install Dotnet SDK 2.2.
8 |
9 | 3) In Rider, install the plugin "Machine Specifications Runner for Rider" (File > Settings > Plugins)
10 |
11 | 4) Make sure everything compiles and the unit tests run and pass (if the tests do not pass, you need to go back and check your versions. If the versions of Rider, Dotnet Core, and the Machine Specifications plugin are not compatible, the tests will not run).
12 |
13 | 5) Fork this repo so that you can push back in your changes.
14 |
15 | ### Prepare Your Mind
16 |
17 | 1) Read up on pairing and katas to get familiar with the concepts. Some starting points might be...
18 |
19 | 2) Get some pointers on how to act while pairing - https://awkwardcoder.com/7-ways-to-win-with-pair-programming-c678c235be2d
20 |
21 | 3) Learn what is a “Kata” and see a few in action - http://codekata.com/
22 |
23 | 4) Check out the [String Calculator](/katas/string_calculator.md) kata we will be learning.
24 |
25 | ### Extras
26 |
27 | If you'd like to use the live templates that Byron uses, check the [templates folder](templates) for template content and instructions.
28 |
--------------------------------------------------------------------------------
/src/Kata-Starter.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kata", "Kata\Kata.csproj", "{E23B873B-193D-44F7-BA0D-8C54AB3AED39}"
4 | EndProject
5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kata.Spec", "Kata.Spec\Kata.Spec.csproj", "{3726D02E-54DA-49C7-9E2D-9D774D8870E8}"
6 | EndProject
7 | Global
8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
9 | Debug|Any CPU = Debug|Any CPU
10 | Release|Any CPU = Release|Any CPU
11 | EndGlobalSection
12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
13 | {E23B873B-193D-44F7-BA0D-8C54AB3AED39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
14 | {E23B873B-193D-44F7-BA0D-8C54AB3AED39}.Debug|Any CPU.Build.0 = Debug|Any CPU
15 | {E23B873B-193D-44F7-BA0D-8C54AB3AED39}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | {E23B873B-193D-44F7-BA0D-8C54AB3AED39}.Release|Any CPU.Build.0 = Release|Any CPU
17 | {3726D02E-54DA-49C7-9E2D-9D774D8870E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
18 | {3726D02E-54DA-49C7-9E2D-9D774D8870E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
19 | {3726D02E-54DA-49C7-9E2D-9D774D8870E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
20 | {3726D02E-54DA-49C7-9E2D-9D774D8870E8}.Release|Any CPU.Build.0 = Release|Any CPU
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/katas/string_calculator.md:
--------------------------------------------------------------------------------
1 | ## String Calculator Kata
2 |
3 | https://osherove.com/tdd-kata-1
4 |
5 | ### Rules:
6 | * Write one spec at a time.
7 | * All previously passing specs must continue to pass
8 | * All new specs must fail for the right reasons before making them pass
9 | * Verbalize thoughts and code
10 | * Follow the process strictly
11 | * No copy/pasta
12 | * No Regex
13 |
14 | ### Process:
15 | 1. Write spec
16 | 2. Red: Failing for the right reasons
17 | 3. Green: Just enough code to make it pass
18 | 4. Refactor: Can I improve the production code or spec without making any previously passing specs fail.
19 | 5. Repeat
20 |
21 | ### Specs
22 | 1. Given the user input is empty when calculating the sum then it should return zero.
23 | 2. Given the user input is one number when calculating the sum then it should return the same number. (example "3" should equal 3)
24 | 3. Given the user input is two numbers when calculating the sum then it should return the sum of those numbers. (example "1,2" should equal 3)
25 | 4. Given the user input is an unknown amount of numbers when calculating the sum then it should return the sum of all the numbers. (example "1,2,3" should equal 6)
26 | 5. Given the user input is multiple numbers with new line and comma delimiters when calculating the sum then it should return the sum of all the numbers. (example "1\n2,3" should equal 6)
27 | 6. Given the user input is multiple numbers with a custom single-character delimiter when calculating the sum then it should return the sum of all the numbers. (example “//;\n1;2” should return 3)
28 | 7. Given the user input contains one negative number when calculating the sum then it should throw an exception "negatives not allowed: x" (where x is the negative number).
29 | 8. Given the user input contains multiple negative numbers mixed with positive numbers when calculating the sum then it should throw an exception "negatives not allowed: x, y, z" (where x, y, z are only the negative numbers).
30 | 9. Given the user input contains numbers larger than 1000 when calculating the sum it should only sum the numbers less than 1001. (example 2 + 1001 = 2)
31 | 10. Given the user input is multiple numbers with a custom multi-character delimiter when calculating the sum then it should return the sum of all the numbers. (example: “//[***]\n1***2***3” should return 6)
32 | 11. Given the user input is multiple numbers with multiple custom delimiters when calculating the sum then it should return the sum of all the numbers. (example “//[*][%]\n1*2%3” should return 6)
33 |
34 | ### Technique and Form
35 | What do we want people to learn from the practice of this kata?
36 |
37 | * Test-Driven Development
38 | * Plain English spec/observation naming
39 | * Top-down, right to left spec implementation
40 | * Defining classes, methods and new specs from the current spec
41 | * Modified Red-Green-Refactor (Red-Green-Red-Green-Red-Green-Red-Green-Red-Green-REFACTOR)
42 | * No automatically green specs
43 | * Failing for the right reason (explaining code path to failure)
44 | * Pair Programming
45 | * Conversational coding
46 | * Ping pong pair programming pattern (p5)
47 | * Mastery of Tools
48 | * Git SCM (Terminal)
49 | * Good commit messages
50 | * Push
51 | * Pull
52 | * Add
53 | * Commit
54 | * Jetbrains Rider
55 | * Automatically run specs on build
56 | * Panels and sub-windows don’t require excessive navigation/mousing
57 | * Refactorings/Keyboard shortcuts
58 | * Limited mouse use
59 | * Create type
60 | * Define field (type inference)
61 | * Move to folder
62 | * Navigate to failures
63 | * Basic editor navigation
64 | * Build
65 | * Run specs
66 | * Create variable after working out the value
67 | * Alt enter
68 | * Dotnet/C#
69 | * Default argument values
70 | * Basic string parsing
71 | * Extension methods
72 | * Select
73 | * Sum
74 | * Functional string/collection manipulation
75 | * Array vs IEnumerable
76 |
--------------------------------------------------------------------------------
/katas/parking_lot.md:
--------------------------------------------------------------------------------
1 | # Parking Lot Kata
2 |
3 | ## Story
4 |
5 | We have a new "smart lot" parking lot. Our parking lot can host many types of vehicles and promotes environmental responsibility by giving discounts to vehicles that are easier on the environment. Even though we have a limited number of spaces today, we hope to expand someday. Also, we hope to start with simple vehicles and start generating revenue before adding more complicated vehicle types.
6 |
7 | ## Rules
8 |
9 | * Follow SOLID principles
10 | * Ping Pong Pairing
11 | * This is a TDD Kata. Red-Green-Refactor (modified)
12 | * Follow "arabic form" when implementing specs.
13 | * No copy pasting
14 | * No Regex
15 |
16 | ## Specs
17 |
18 | Scenario: Normal Car, Plenty of Space, $5
19 | ```
20 | Given a parking lot with 50 spaces
21 | And a normal car
22 | When the vehicle stays for one day
23 | Then the driver is charged $5
24 | And the lot is left with 49 spaces
25 | ```
26 | Scenario: Normal Car, One Space Left
27 | ```
28 | Given a parking lot with 1 spaces
29 | And a normal car
30 | When the vehicle stays for one day
31 | Then the driver is charged $5
32 | And the lot is left with 0 spaces
33 | ```
34 | Scenario: Normal Car, No Space
35 | ```
36 | Given a parking lot with 0 spaces
37 | And a normal car
38 | When the vehicle attempts to enters the lot
39 | Then the driver is charged $0
40 | And the car is rejected
41 | ```
42 | Scenario: Electric Car, Plenty of Space, 50% discount
43 | ```
44 | Given a parking lot with 50 spaces
45 | And an electric car
46 | When the vehicle stays for one day
47 | Then the driver is charged $2.50
48 | And the lot is left with 49 spaces
49 | ```
50 | Scenario: Motocycle, Plenty of Space, 1/2 space
51 | ```
52 | Given a parking lot with 50 spaces
53 | And a motorcycle
54 | When the vehicle stays for one day
55 | Then the driver is charged $3.00
56 | And the lot is left with 49.5 spaces
57 | ```
58 | Scenario: Normal Car, Trump Sticker, Charge Double
59 | ```
60 | Given a parking lot with 50 spaces
61 | And a normal car
62 | And the car has a trump sticker
63 | When the vehicle stays for one day
64 | Then the driver is charged $10
65 | And the lot is left with 49 spaces
66 | ```
67 | Scenario: Bus, Plenty of Space, 2 Spaces, $9
68 | ```
69 | Given a parking lot with 50 spaces
70 | And a bus
71 | When the vehicle stays for one day
72 | Then the driver is charged $9.00
73 | And the lot is left with 48 spaces
74 | ```
75 | Scenario: Electric Bus, Plenty of Space, 50% discount
76 | ```
77 | Given a parking lot with 50 spaces
78 | And an electric bus
79 | When the vehicle stays for one day
80 | Then the driver is charged $4.50
81 | And the lot is left with 48 spaces
82 | ```
83 | Scenario: Helicopter, Plenty of space, 8 Spaces, $35
84 | ```
85 | Given a parking lot with 50 spaces
86 | And a helicopter
87 | When the vehicle stays for one day
88 | Then the driver is charged $35
89 | And the lot is left with 42 spaces
90 | ```
91 | Scenario: Helicopter, Plenty of space, 2 Days
92 | ```
93 | Given a parking lot with 50 spaces
94 | And a helicopter
95 | When the vehicle stays for two days
96 | Then the driver is charged $70
97 | And the lot is left with 42 spaces
98 | ```
99 | Scenario: 20% discount for 3 or more days
100 | ```
101 | Given a parking lot with 50 spaces
102 | And a bus
103 | When the vehicle stays for four days
104 | Then the driver is charged $28.80
105 | And the lot is left with 48 spaces
106 | ```
107 | Scenario: 30% discount for 6 days or more
108 | ```
109 | Given a parking lot with 50 spaces
110 | And a normal car
111 | When the vehicle stays for eight days
112 | Then the driver is charged $28
113 | And the lot is left with 49 spaces
114 | ```
115 |
116 | ## Techniques/Practices
117 |
118 | This is what you should be learning through this kata.
119 |
120 | [To Be Determined]
121 |
122 | ## Inspiration
123 |
124 | This kata was inspired by https://github.com/kamranahmedse/design-patterns-for-humans.
125 |
--------------------------------------------------------------------------------