diff --git a/arrange-act-assert/README.md b/arrange-act-assert/README.md new file mode 100644 index 000000000..02b7ee8b7 --- /dev/null +++ b/arrange-act-assert/README.md @@ -0,0 +1,30 @@ +--- +layout: pattern +title: Arrange/Act/Assert +folder: arrange-act-assert +permalink: /patterns/arrange-act-assert/ +categories: Idiom +tags: + - Testing +--- + +## Also known as +Given/When/Then + +## Intent +The Arrange/Act/Assert (AAA) is a pattern for organizing unit tests. +It breaks tests down into three clear and distinct steps: +1. Arrange: Perform the setup and initialization required for the test. +2. Act: Take action(s) required for the test. +3. Assert: Verify the outcome(s) of the test. + +## Applicability +Use Arrange/Act/Assert pattern when + +* you need to structure your unit tests so they're easier to read, maintain, and enhance. + +## Credits + +* [Arrange, Act, Assert: What is AAA Testing?](https://blog.ncrunch.net/post/arrange-act-assert-aaa-testing.aspx) +* [Bill Wake: 3A – Arrange, Act, Assert](https://xp123.com/articles/3a-arrange-act-assert/) +* [Martin Fowler: GivenWhenThen](https://martinfowler.com/bliki/GivenWhenThen.html) diff --git a/arrange-act-assert/etc/arrange-act-assert.urm.puml b/arrange-act-assert/etc/arrange-act-assert.urm.puml new file mode 100644 index 000000000..4b22d2a4e --- /dev/null +++ b/arrange-act-assert/etc/arrange-act-assert.urm.puml @@ -0,0 +1,11 @@ +@startuml +package com.iluwatar.arrangeactassert { + class Cash { + - amount : int + ~ Cash(amount : int) + ~ count() : int + ~ minus(subtrahend : int) : boolean + ~ plus(addend : int) + } +} +@enduml \ No newline at end of file diff --git a/arrange-act-assert/pom.xml b/arrange-act-assert/pom.xml new file mode 100644 index 000000000..bb0387e7a --- /dev/null +++ b/arrange-act-assert/pom.xml @@ -0,0 +1,44 @@ + + + + + java-design-patterns + com.iluwatar + 1.23.0-SNAPSHOT + + 4.0.0 + + arrange-act-assert + + + junit + junit + test + + + \ No newline at end of file diff --git a/arrange-act-assert/src/main/java/com/iluwatar/arrangeactassert/Cash.java b/arrange-act-assert/src/main/java/com/iluwatar/arrangeactassert/Cash.java new file mode 100644 index 000000000..71269359e --- /dev/null +++ b/arrange-act-assert/src/main/java/com/iluwatar/arrangeactassert/Cash.java @@ -0,0 +1,57 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.arrangeactassert; + +/** + * Arrange/Act/Assert (AAA) is a unit test pattern. In this simple example, we have a ({@link Cash}) + * object for plus, minus and counting amount. + */ +public class Cash { + + private int amount; + + Cash(int amount) { + this.amount = amount; + } + + //plus + void plus(int addend) { + amount += addend; + } + + //minus + boolean minus(int subtrahend) { + if (amount >= subtrahend) { + amount -= subtrahend; + return true; + } else { + return false; + } + } + + //count + int count() { + return amount; + } +} diff --git a/arrange-act-assert/src/test/java/com/iluwatar/arrangeactassert/CashAAATest.java b/arrange-act-assert/src/test/java/com/iluwatar/arrangeactassert/CashAAATest.java new file mode 100644 index 000000000..d7841843d --- /dev/null +++ b/arrange-act-assert/src/test/java/com/iluwatar/arrangeactassert/CashAAATest.java @@ -0,0 +1,99 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.arrangeactassert; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Arrange/Act/Assert (AAA) is a pattern for organizing unit tests. It is a way to structure your + * tests so they're easier to read, maintain and enhance. + * + *

It breaks tests down into three clear and distinct steps: + *

1. Arrange: Perform the setup and initialization required for the test. + *

2. Act: Take action(s) required for the test. + *

3. Assert: Verify the outcome(s) of the test. + * + *

This pattern has several significant benefits. It creates a clear separation between a test's + * setup, operations, and results. This structure makes the code easier to read and understand. If + * you place the steps in order and format your code to separate them, you can scan a test and + * quickly comprehend what it does. + * + *

It also enforces a certain degree of discipline when you write your tests. You have to think + * clearly about the three steps your test will perform. But it makes tests more natural to write at + * the same time since you already have an outline. + * + *

In ({@link CashAAATest}) we have four test methods. Each of them has only one reason to + * change and one reason to fail. In a large and complicated code base, tests that honor the single + * responsibility principle are much easier to troubleshoot. + */ +public class CashAAATest { + + @Test + public void testPlus() { + //Arrange + var cash = new Cash(3); + //Act + cash.plus(4); + //Assert + assertEquals(cash.count(), 7); + } + + @Test + public void testMinus() { + //Arrange + var cash = new Cash(8); + //Act + var result = cash.minus(5); + //Assert + assertTrue(result); + assertEquals(cash.count(), 3); + } + + @Test + public void testInsufficientMinus() { + //Arrange + var cash = new Cash(1); + //Act + var result = cash.minus(6); + //Assert + assertFalse(result); + assertEquals(cash.count(), 1); + } + + @Test + public void testUpdate() { + //Arrange + var cash = new Cash(5); + //Act + cash.plus(6); + var result = cash.minus(3); + //Assert + assertTrue(result); + assertEquals(cash.count(), 8); + } +} diff --git a/arrange-act-assert/src/test/java/com/iluwatar/arrangeactassert/CashAntiAAATest.java b/arrange-act-assert/src/test/java/com/iluwatar/arrangeactassert/CashAntiAAATest.java new file mode 100644 index 000000000..3f8c33d5e --- /dev/null +++ b/arrange-act-assert/src/test/java/com/iluwatar/arrangeactassert/CashAntiAAATest.java @@ -0,0 +1,59 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.arrangeactassert; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * ({@link CashAAATest}) is an anti-example of AAA pattern. This test is functionally correct, but + * with the addition of new feature, it needs refactoring. There are an awful lot of steps in that + * test method, but it verifies the class' important behavior in just eleven lines. It violates the + * single responsibility principle. If this test method failed after a small code change, it might + * take some digging to discover why. + */ +public class CashAntiAAATest { + + @Test + public void testCash() { + //initialize + var cash = new Cash(3); + //test plus + cash.plus(4); + assertEquals(cash.count(), 7); + //test minus + cash = new Cash(8); + assertTrue(cash.minus(5)); + assertEquals(cash.count(), 3); + assertFalse(cash.minus(6)); + assertEquals(cash.count(), 3); + //test update + cash.plus(5); + assertTrue(cash.minus(5)); + assertEquals(cash.count(), 3); + } +} diff --git a/pom.xml b/pom.xml index b81cfe8d4..97deda703 100644 --- a/pom.xml +++ b/pom.xml @@ -184,6 +184,7 @@ combinator update-method leader-followers + arrange-act-assert