Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion EXERCISE1.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Here is how one might design a domain model for the above user story:
> **Time to analyse**
>
> Evaluate the user story and the domain model above. What assumptions did the developer have to make and what would you do differently?
>
>
> Create your own domain model for the user story above, try to come up with a different solution than the model provided. You can use a table like the one above, a spreadsheet, pen and paper, whatever you'd like. Share your work in your cohorts classroom channel when you're done.

### Exercise
Expand All @@ -36,13 +36,28 @@ As a supermarket shopper,
So that I can pay for products at checkout,
I'd like to be able to know the total cost of items in my basket.
```
| Classes | Member Variables | Methods | Scenario | Outputs |
|----------|-------------------------|----------------------------------------------------|-------------------------------------|---------|
| | List<Product> Inventory | `sumBasket(HashMap<Product, Integer> basketItems)` | If list is empty | 0.00 |
| | | (key=product, value=amountPurchased) | If list is not empty | Double |
| | | | Partial check-out (returned items?) | Double |
| | | `addToBasket(Product product)` | If name is in inventory list | true |
| `Basket` | | | If name is not in inventory list | false |
| | | `removeFromBasket(Product product)` | If name is in buyer's list | true |
| | | | If name is not in buyer's list | false |


```
As an organised individual,
So that I can evaluate my shopping habits,
I'd like to see an itemised receipt that includes the name and price of the products
I bought as well as the quantity, and a total cost of my basket.
```
| Classes | Member Variables | Methods | Scenario | Outputs |
|-------------|----------------------------------------|---------------|--------------------------------------------------------------|---------|
| `Receipt` | HashMap<Product, Integer> basketItems | `viewItems()` | If list is empty | String |
| | | | If list is not empty | String |
| | | | Partial check-out (returned items? reimbursements? bonuses?) | String |

- Add your domain models to this repository as a file named `domain-model`. This should either be a `.md` file like this one, or a screenshot / picture of your work.
- Your model doesn't have to look like the example provided in this file. If you feel like you need more or less columns, feel free to go with that. There is no "right way" to do this kind of thing, we're just designing a system to make our lives easier when it comes to the coding part.
6 changes: 4 additions & 2 deletions EXERCISE2.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# 2. Use the Red Green Refactor workflow to implement a solution

There is a class in `./src/main/java/com.booleanuk/code/CohortManager.java` and a test class in `./src/test/java/com.booleanuk/core/CohortManagerTest.java`. Your morning teacher will demonstrate the process of creating tests from the domain model below, and then using those tests to develop robust source code.
There is a class in `./src/main/java/com.booleanuk/code/CohortManager.java` and a test class in `./src/test/java/com.booleanuk/core/CohortManagerTest.java`.
Your morning teacher will demonstrate the process of creating tests from the domain model below, and then using those tests to develop robust source code.

This is known as the **Red, Green, Refactor** workflow; an important discipline to practice. Simple to learn yet difficult to master.

When writing software using this Test Driven Development approach, we don't write a complete test or complete method at a time. We write *just enough* of a test for it to fail, then write *just enough* source code to make the test pass, then refactor until the test fails and repeat this cycle.
When writing software using this Test Driven Development approach, we don't write a complete test or complete method at a time.
We write *just enough* of a test for it to fail, then write *just enough* source code to make the test pass, then refactor until the test fails and repeat this cycle.

What we are creating here are known as *unit tests*, tests that verify a single unit of our application is working correctly. They should be as small as possible, usually broken down into three parts:

Expand Down
24 changes: 24 additions & 0 deletions src/main/java/com/booleanuk/core/Basket.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.booleanuk.core;

import java.util.HashMap;

public class Basket {
public HashMap<String, Integer> items;

public Basket() {
this.items = new HashMap<String, Integer>();
}

public boolean add(String product, int price) {
return price >= 0 && product.strip().length() != 0
&& this.items.putIfAbsent(product, price) == null;
}

public int total() {
return this.items.values()
.stream()
.mapToInt(Integer::intValue)
.sum();

}
}
60 changes: 60 additions & 0 deletions src/test/java/com/booleanuk/core/BasketTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.booleanuk.core;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class BasketTest {
@Test
public void testAddProductToBasket() {
Basket basket = new Basket();
Assertions.assertTrue(basket.add("Apple", 2));
Assertions.assertEquals(1, basket.items.size());
Assertions.assertTrue(basket.items.containsKey("Apple"));
Assertions.assertEquals(2, basket.items.get("Apple").intValue());
}

@Test
public void testAddDuplicateProductToBasket() {
Basket basket = new Basket();
basket.add("Banana", 3);
Assertions.assertFalse(basket.add("Banana", 2));
Assertions.assertEquals(1, basket.items.size());
Assertions.assertTrue(basket.items.containsKey("Banana"));
Assertions.assertEquals(3, basket.items.get("Banana").intValue());
}

@Test
public void testAddMultipleProductsToBasket() {
Basket basket = new Basket();
Assertions.assertTrue(basket.add("Orange", 4));
Assertions.assertTrue(basket.add("Grapes", 5));
Assertions.assertEquals(2, basket.items.size());
}

@Test
public void testAddAndGetTotalWithEmptyBasket() {
Basket basket = new Basket();
Assertions.assertEquals(0, basket.total());
}

@Test
public void testTotalWithProductsInBasket() {
Basket basket = new Basket();
basket.add("Orange", 4);
basket.add("Grapes", 5);
Assertions.assertEquals(9, basket.total());
}

@Test
public void testAddProductWithNegativePriceToBasket() {
Basket basket = new Basket();
Assertions.assertFalse(basket.add("Chips", -2)); // Negative price should not be accepted
Assertions.assertEquals(0, basket.items.size());
}
@Test
public void testAddProductWithMissingNameInBasket() {
Basket basket = new Basket();
Assertions.assertFalse(basket.add(" ", 2)); // Negative price should not be accepted
Assertions.assertEquals(0, basket.items.size());
}
}