package demo;

import static org.junit.jupiter.api.Assertions.*;

import java.util.Arrays;
import java.util.Collection;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import sut.Calculator;

class CalculatorTest_demo 
{
	private Calculator cal = new Calculator();
	// controllability 
	
	@BeforeAll
	static void setUpBeforeClass() throws Exception {
	}

	@AfterAll
	static void tearDownAfterClass() throws Exception {
	}

	@BeforeEach
	void setUp() throws Exception {
		cal = new Calculator();
	}

	@AfterEach
	void tearDown() throws Exception {
	}

	// id:
	// purpose:
	// precond, postcond: 
	// input: 5, 4
	// expect: 9
	@Test
	void testAdd() 
	{
		// 1. setup
		// 2. exe
		// 3. assert
//		Calculator cal = new Calculator();
		assertEquals(9, cal.add(5, 4)); 
	}

	
	@Test
	@DisplayName("customized name by อัปสร")
	void testAdd_2() 
	{
		assertEquals(9, cal.add(5, 4)); 
	}
	
	@Test
	void testAddMultipleAssertion() 
	{
		assertEquals(1, cal.add(5, 4)); 
		assertEquals(10, cal.add(0, 0)); 
		assertEquals(1, cal.add(-5, 4)); 
	}	

	@Test
	void testAddGroupAssertion() 
	{
		// assertEquals(9, cal.add(0, 1));
		assertAll("optional string",
				() -> assertEquals(1, cal.add(5, 4)), 
				() -> assertEquals(10, cal.add(0, 0)), 
				() -> assertEquals(1, cal.add(-5, 4))
				);
	}	

	@Test
	void testDivideByZero_1()
	{
		try {
			cal.divide(4, 0);
		} catch (ArithmeticException e) {
			System.out.println(e.getMessage());
		}
	}
	
	@Test
	void testDivideByZero_2()
	{
		assertThrows(ArithmeticException.class, 
				() -> cal.divide(4, 0)); 
	}

	// data-driven
	//1. array of test cases
	//2. use this array in test method
	
	// test cases (add)  
	// pos + pos 
	// pos + zero
	// pos + neg
	// neg + neg
	// neg + zero
	// zero + zero
	static Collection<Object[]> calcValues()
	{
	   return Arrays.asList(new Object[][] { {1,1,2}, {0,4,4}, {2,-3,-4}, {-2,-5,-7}, {-2,0,0-2}, {0,0,0} } );
	}
	
    @ParameterizedTest(name="Test number {index} => we entered a={0}, b={1}, sum={2}")
//	@ParameterizedTest()   
    @MethodSource("calcValues") 
    void testCalculatorWithDataDriven(int a, int b, int sum)
    {
	    assertTrue(sum == cal.add(a, b), "test add(" + a + ", " + b + ")");	   
    }
	
}
