TDD By Example

There is an offer on Gatsby hair cream –
buy x item get y item free– if you buy 2 gatsby hair cream you will get 1 free.
there is no offer on ‘Bvlgiri soap’.

Requirement: Apply offer on shopping cart
When: Add 5 unit of ‘Gatsby hair cream’, unit price 30 Rupees.
Then:
The product count of cart should be 1.
– The total value of cart should be 120 rupees.

It’s time to accommodate offer in our Shopping Cart Application.
As we can see that the ShoppingCart class has all the products and we are going to apply offers on the products. Therefore ShoppingCart should know about the offers. Currently we have two types of offer- Buy x items get y items free and no offer. We can’t create all the offers in ShoppingCart. As a matter of fact an offer related to a product should be passed by the client to the ShoppingCart so that cart can apply the offer specific to a particular product.

Create an interface IOffer

package com.tdd.shoppingcart;

public interface IOffer {

	public void applyOffer(Product product);
}

Now create two implementation- BuyXItemGetYItemFreeOffer and NoOffer

package com.tdd.shoppingcart;

public class BuyXItemGetYItemFreeOffer implements IOffer {

	private int XItem;
	private int YItem;
	
	public BuyXItemGetYItemFreeOffer(int xItem, int yItem) {
		XItem = xItem;
		YItem = yItem;
	}

	@Override
	public void applyOffer(Product product) {
		
	}
	//get/set
}
package com.tdd.shoppingcart;

public class NoOffer implements IOffer{

	@Override
	public void applyOffer(Product product) {
		// Nothing to do here
	}
}

It’s time to add a new test for above requirement. Add 5 unit of “Gatsby hair cream” for 150. Make an assertion for product count 1 and cart value after applying offer is 120.0.

package com.tdd.test.shoppingcart;

import org.junit.Assert;
import org.junit.Test;

import com.tdd.shoppingcart.BuyXItemGetYItemFreeOffer;
import com.tdd.shoppingcart.IOffer;
import com.tdd.shoppingcart.NoOffer;
import com.tdd.shoppingcart.Product;
import com.tdd.shoppingcart.ShoppingCart;

public class ShoppingCartAppTest {

	@Test
	public void testCreateEmptyShoppingCart() {
		ShoppingCart cart = new ShoppingCart();
		Assert.assertEquals(0, cart.getProductCount());
	}
	
	@Test
	public void testAddSingleProductToShoppingCart() {
		ShoppingCart cart = new ShoppingCart();
		Product product = new Product("Gatsby hair cream", 1, 30.0);
		cart.addProduct(product);
		Assert.assertEquals(1, cart.getProductCount());
		Assert.assertEquals(30.0, cart.getTotalCartValue(),0.0);
	}
	
	@Test
	public void addDifferentProductsToTheCart(){
		ShoppingCart cart = new ShoppingCart();
		Product gatsByCream = new Product("Gatsby hair cream", 1, 30.0);
		Product bvlgiriSoap = new Product("Bvlgiri Soap", 1, 100.0);
		cart.addProduct(gatsByCream);
		cart.addProduct(bvlgiriSoap);
		Assert.assertEquals(2, cart.getProductCount());
		Assert.assertEquals(130.0, cart.getTotalCartValue(),0.0);
	}
	
	@Test
	public void testAddMultipleQuantityOfAProductAndApplyOfferToCart() {
		IOffer offer = new BuyXItemGetYItemFreeOffer(2,1);
		ShoppingCart cart = new ShoppingCart();
		cart.setOffer(offer);
		Product product = new Product("Gatsby hair cream", 5, 150.0);
		cart.addProduct(product);
		Assert.assertEquals(1, cart.getProductCount());
		Assert.assertEquals(120.0, cart.getTotalCartValue(),0.0);
	}
}

The above tests will not compile since ShoppingCart doesn’t have setOffer() method. Let’s create setOffer(IOffer) method to ShoppingCart.

package com.tdd.shoppingcart;

import java.util.ArrayList;
import java.util.List;

public class ShoppingCart {

	private List<Product> productList = new ArrayList<>();
	private double totalCartValue;
	private IOffer offer;

	public int getProductCount() {
		return productList.size();
	}

	public void addProduct(Product product) {
		productList.add(product);
	}

	public double getTotalCartValue() {
		if (productList.size() > 0) {
			for (Product product : productList) {
				totalCartValue = totalCartValue + product.getTotalPrice();
			}
		}
		return totalCartValue;
	}

	public void setOffer(IOffer offer) {
		this.offer = offer;
	}
}

Now run the test. The last test will fail since we haven’t applied the offer yet and also we have not written any logic for the offer BuyXItemGetYItem free.
TDD-By-Example13

Add offer logic to the class BuyXItemGetYItemFreeOffer.

package com.tdd.shoppingcart;

public class BuyXItemGetYItemFreeOffer implements IOffer {

	private int XItem;
	private int YItem;

	public BuyXItemGetYItemFreeOffer(int xItem, int yItem) {
		XItem = xItem;
		YItem = yItem;
	}

	@Override
	public void applyOffer(Product product) {
		if (product.getQuantity() >= XItem) {
			int freeProductQty = product.getQuantity() / (XItem + YItem);
			double unitPrice = product.getTotalPrice() / product.getQuantity();
			double discount = unitPrice * freeProductQty;
			product.setTotalPrice(product.getTotalPrice() - discount);
		}
	}
	// get/set

}

Apply offer in the ShoppingCart while adding the product to the Cart.

package com.tdd.shoppingcart;

import java.util.ArrayList;
import java.util.List;

public class ShoppingCart {

	private List<Product> productList = new ArrayList<>();
	private double totalCartValue;
	private IOffer offer;

	public int getProductCount() {
		return productList.size();
	}

	public void addProduct(Product product) {
		if(offer != null){
			offer.applyOffer(product);//apply offer
		}
		productList.add(product);
	}

	public double getTotalCartValue() {
		if (productList.size() > 0) {
			for (Product product : productList) {
				totalCartValue = totalCartValue + product.getTotalPrice();
			}
		}
		return totalCartValue;
	}

	public void setOffer(IOffer offer) {
		this.offer = offer;
	}
	
	
}

Now run the test again. It will pass without any problem.
TDD-By-Example15

Requirement: Add different Products and apply offer to shopping cart
When:
– Add 3 unit of ‘Gatsby hair cream’, unit price 30 Rupees.
– Add 2 unit of ‘Bvlgiri Soap’, unit price 100 Rupees.

Then:
– The product count of the cart should be 2.
– The total value of cart should be 260.0 rupees.

Add a test for the above requirement to our test class.

    @Test
	public void addDifferentProductsAndAppyOfferToTheCart(){
		IOffer offer = new BuyXItemGetYItemFreeOffer(2,1);
		ShoppingCart cart = new ShoppingCart();
		Product gatsByCream = new Product("Gatsby hair cream", 3, 90.0);
		Product bvlgiriSoap = new Product("Bvlgiri Soap", 2, 200.0);
		cart.setOffer(offer);
		cart.addProduct(gatsByCream);
		cart.setOffer(new NoOffer());//No offer for the Soap
		cart.addProduct(bvlgiriSoap);
		Assert.assertEquals(2, cart.getProductCount());
		Assert.assertEquals(260.0, cart.getTotalCartValue(),0.0);
	}

This test will pass without any refactoring.
Go to the next page – Click on the below red circle with page number.

Leave a Reply

avatar

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  Subscribe  
Notify of