
Make your testing Groovy © ASERT 2006 Dr Paul King Groovy Lead for Object Computing Inc. - 2016 @paulk_asert http:/slideshare.net/paulk_asert/make-tests-groovy https://github.com/paulk-asert/MakeTestingGroovy Why test with Groovy? with test Why © ASERT 2006-2016 Why test with Groovy? • Wrong first question! • … but great second question? © ASERT 2006 - 2016 • Consider first the task at hand and the organization and people fit! “People Fit” / “Organization Fit” • People – Developers (familiarity with languages) – Testers (tools language familiarity) – Responsibility to create/run/maintain – BAs/SMEs (ability to read technical tests) © ASERT 2006 – Consider both development and maintenance - 2016 – Expected feedback from tests (JUnit/Reports) • Organization – Maturity level – Degree of automation – Tools in use – Need for adaptability Why Test With Groovy? • Advantages – Easy to learn – Particularly good for Java shops – Easy to plug and play different testing tools – Good community & tools for professional agile © ASERT 2006 • Disadvantages - 2016 – Requires JVM – Less advantages if your developers using Python, .Net, PHP – Maybe your testers already know Ruby Scripting/Dynamic Languages • Advantages – Lend themselves to succinct code/DSLs – Powerful – Increased Refactoring – Increased Reuse © ASERT 2006 – Less prone to Brittleness - 2016 – Flexibility for tool integration – Open APIs provide extensibility • Disadvantages – Can be too low level – Sometimes less tool support Test Characteristics… • Coverage/Traceability – Requirement coverage/traceability – Code coverage: line, branch, path, state – Transactional Tracing © ASERT 2006 • Purpose – Unit, Integration, System, Customer - 2016 • Manageability – Removing duplication – Managing lifecycle: shared setUp/tearDown (@Before @After) …Test Characteristics • Handling test data – Data-driven, databases, Spreadsheets, tables, keywords, random, model-driven – Large Test Volumes © ASERT 2006 – Speed of feedback, performance testing • Tool evolution, longevity, cost, - 2016 support, documentation – Open Source/Commercial, Critical mass/popularity • Combinability Key Testing Practices… • Use testing DSL’s • Look to move up the testing stack – It used to be all about the driver – Now the driver is hidden in the © ASERT 2006 framework or tool stack • Apply good testing practices - 2016 – Pareto analysis, bug clusters, mutation testing, test early, all pairs/equivalence partitions/orthogonal array testing, risk-based test selection, coding for testability, use CI, boundary value analysis, defensive programming …Key Testing Practices • Plug and play testing tools – Run different drivers with different runners and different tools • Complement automated tests with © ASERT 2006 exploration • Expand testing scope - 2016 – Test environment readiness, test deployments Groovy and Testing Tool Spectrum* © ASERT 2006 - 2016 * Tools/libraries/frameworks don't always neatly fall into one category – still useful conceptually What is Groovy? “Groovy is like a super version of Java. It leverages Java features but adds productivity features and provides great flexibility and © ASERT 2006 extensibility.” - 2016 Groovy = Java – boiler plate code + closures (1st class FP) + extensible type system + runtime & compile-time metaprogramming + flexible grammar (DSLs) + scripting & GDK library Groovy starter System.out.println("Hello, World!"); // supports Java syntax println 'Hello, World!' // but can remove some syntax String name = 'Guillaume' // Explicit typing/awareness println "$name, I'll get the car." // Gstring (interpolation) def longer = """${name}, the car is in the next row.""" // multi-line, implicit type © ASERT 2006 assert 0.5 == 1/2 // BigDecimal equals() assert 0.1 + 0.2 == 0.3 // and arithmetic - 2016 def printSize(obj) { // implicit/duck typing print obj?.size() // safe dereferencing } def pets = ['ant', 'bee', 'cat'] // literal list syntax pets.each { pet -> // closure support assert pet < 'dog' // overloading '<' on String } // or: for (pet in pets)... Target audience • Testing for developers – Organising tests – Running tests – Data generation – Mocking – What can be tested – Code coverage • Testing beyond developers – Structuring – Better reporting – Data-driven – Domain specific language (DSL) – Test coverage Testing Frameworks • None • JUnit 3 • JUnit 4 • JUnit 5 • TestNG • Spock Testing Frameworks • None ??? • JUnit 3 • JUnit 4 • JUnit 5 • TestNG • Spock Testing Frameworks • None ??? – Groovy deems testing so important that it comes with built-in testing: – Built-in asserts, mocks – Built-in JUnit 3 GroovyTestCase and utilities – Built-in runners for tests – Bundled JUnit 4 • JUnit 3 • JUnit 4 • JUnit 5 • TestNG • Spock Built-in assertions class Converter { static celsius (fahrenheit) { (fahrenheit - 32) * 5 / 9 } } © ASERT 2006 - 2016 import static Converter.celsius assert 20 == celsius(68) assert 35 == celsius(95) assert -17 == celsius(0).toInteger() assert 0 == celsius(32) Built-in assertions • But what about errors? © ASERT 2006 • Groovy’s power Assert mechanism gives a friendly description of what went wrong - 2016 Built-in assertions • But what about errors? © ASERT 2006 • Groovy’s power Assert mechanism gives a friendly description of what went wrong - 2016 GroovyTestCase (extends JUnit 3) import org.junit.Assert import static Converter.celsius import static org.junit.Assert.assertEquals class SimpleGroovyTest extends GroovyTestCase { © ASERT 2006 void testShouldConvert() { assert Converter.celsius(68) == 20 assert Converter.celsius(212) == 100, "Should convert boiling" assertEquals("Should convert freezing", 0.0, celsius(32.0)) - 2016 assertEquals("Should convert nearly freezing", 0.0, celsius(32.1), 0.1) } } JUnit4 import org.junit.Test import static org.junit.Assert.assertEquals import static Converter.celsius class SimpleJUnit4Test { © ASERT 2006 @Test void shouldConvert() { assert celsius(68) == 20 - 2016 assert celsius(212) == 100, "Should convert boiling" assertEquals("Should convert freezing", 0.0, celsius(32.0)) assertEquals("Also for nearly freezing", 0.0, celsius(32.1), 0.1) } } JUnit5 @Grab('org.junit.platform:junit-platform-runner:1.0.0-M2') @Grab('org.junit.jupiter:junit-jupiter-engine:5.0.0-M2') import org.junit.jupiter.api.Test import org.junit.platform.runner.JUnitPlatform import org.junit.runner.RunWith import static Converter.celsius © ASERT 2006 @RunWith(JUnitPlatform) class ConverterJUnit5Tests { - @Test 2016 void freezing() { assert celsius(32) == 0 } @Test void boiling() { assert celsius(212) == 100 } } JUnit5 @Grab('org.junit.platform:junit-platform-runner:1.0.0-M2') @Grab('org.junit.jupiter:junit-jupiter-engine:5.0.0-M2') import org.junit.jupiter.api.Test import org.junit.platform.runner.JUnitPlatform import org.junit.runner.RunWith import static Converter.celsius © ASERT 2006 @RunWith(JUnitPlatform) class ConverterJUnit5Tests { - @Test 2016 void freezing() { assert celsius(32) == 0 } @Test void boiling() { assert celsius(212) == 100 } } Spock - BDD style @Grab('org.spockframework:spock-core:1.0-groovy-2.4') import spock.lang.Specification class GivenWhenThenSpec extends Specification { def "test adding a new item to a set"() { © ASERT 2006 given: def items = [4, 6, 3, 2] as Set - 2016 when: items << 1 then: items.size() == 5 } } Parameterized import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized import org.junit.runners.Parameterized.Parameters import static Converter.celsius @RunWith(Parameterized) class DataDrivenJUnitTest { private c, f, scenario @Parameters static scenarios() {[ [0, 32, 'Freezing'], © ASERT 2006 [20, 68, 'Garden party conditions'], [35, 95, 'Beach conditions'], [100, 212, 'Boiling'] ]*.toArray()} - 2016 DataDrivenJUnitTest(c, f, scenario) this.c = c this.f = f this.scenario = scenario } @Test void convert() { def actual = celsius(f) def msg = "$scenario: ${f}°F should convert into ${c}°C" assert c == actual, msg } } Spock @Grab('org.spockframework:spock-core:1.0-groovy-2.4') import spock.lang.* import static Converter.celsius class SpockDataDriven extends Specification { def "test temperature scenarios"() { expect: © ASERT 2006 celsius(tempF) == tempC where: - 2016 scenario | tempF || tempC 'Freezing' | 32 || 0 'Garden party conditions' | 68 || 20 'Beach conditions' | 95 || 35 'Boiling' | 212 || 100 } } Spock - Celsius @Grab('org.spockframework:spock-core:1.0-groovy-2.4') import spock.lang.* import static Converter.celsius class SpockDataDriven extends Specification { @Unroll def "Scenario #scenario: #tempFºF should convert to #tempCºC"() { expect: celsius(tempF) == tempC © ASERT 2006 where: scenario | tempF || tempC 'Freezing' | 32 || 0 - 2016 'Garden party conditions' | 68 || 20 'Beach conditions' | 95 || 34 'Boiling' | 212 || 100 } } Spock - Celsius @Grab('org.spockframework:spock-core:1.0-groovy-2.4') import spock.lang.* import static Converter.celsius class SpockDataDriven extends Specification { @Unroll def "Scenario #scenario: #tempFºF should convert to #tempCºC"() { expect: celsius(tempF) == tempC © ASERT 2006 where: scenario | tempF || tempC 'Freezing' | 32 || 0 - 2016 'Garden party conditions' | 68 || 20 'Beach conditions' | 95 || 34 'Boiling' | 212 || 100 } } Spock - Mocks @Grab('org.spockframework:spock-core:1.0-groovy-2.4') import spock.lang.Specification class SpockMock extends Specification { def "buy ticket for a movie theater"() { given: © ASERT 2006 def purchase = new Purchase("Lord of the Rings", 2) MovieTheater theater = Mock() theater.hasSeatsAvailable("Lord of
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages74 Page
-
File Size-