renamed back to testing-modules, pulled together testing-modules-2 modules into single module

This commit is contained in:
Sjmillington
2019-09-04 18:03:26 +01:00
parent ff871516ee
commit ce9ea390ba
558 changed files with 16 additions and 75 deletions

View File

@@ -0,0 +1 @@
/report-*.json

View File

@@ -0,0 +1,5 @@
### Relevant articles
- [Introduction to Testing with Spock and Groovy](http://www.baeldung.com/groovy-spock)
- [Difference Between Stub, Mock, and Spy in the Spock Framework](https://www.baeldung.com/spock-stub-mock-spy)
- [Guide to Spock Extensions](https://www.baeldung.com/spock-extensions)

View File

@@ -0,0 +1,56 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.spockframework</groupId>
<artifactId>groovy-spock</artifactId>
<version>1.0-SNAPSHOT</version>
<name>groovy-spock</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>${spock-core.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>${groovy-all.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>${gmavenplus-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<spock-core.version>1.3-groovy-2.4</spock-core.version>
<groovy-all.version>2.4.7</groovy-all.version>
<gmavenplus-plugin.version>1.5</gmavenplus-plugin.version>
</properties>
</project>

View File

@@ -0,0 +1,7 @@
package mocks;
public interface EventPublisher {
void publish(String addedOfferId);
}

View File

@@ -0,0 +1,5 @@
package mocks;
public class ExternalItemProviderException extends RuntimeException {
}

View File

@@ -0,0 +1,36 @@
package mocks;
import java.util.Objects;
public class Item {
private final String id;
private final String name;
public Item(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Item item = (Item) o;
return Objects.equals(id, item.id) &&
Objects.equals(name, item.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}

View File

@@ -0,0 +1,9 @@
package mocks;
import java.util.List;
public interface ItemProvider {
List<Item> getItems(List<String> itemIds);
}

View File

@@ -0,0 +1,37 @@
package mocks;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class ItemService {
private final ItemProvider itemProvider;
private final EventPublisher eventPublisher;
public ItemService(ItemProvider itemProvider, EventPublisher eventPublisher) {
this.itemProvider = itemProvider;
this.eventPublisher = eventPublisher;
}
List<Item> getAllItemsSortedByName(List<String> itemIds) {
List<Item> items;
try{
items = itemProvider.getItems(itemIds);
} catch (RuntimeException ex) {
throw new ExternalItemProviderException();
}
return items.stream()
.sorted(Comparator.comparing(Item::getName))
.collect(Collectors.toList());
}
void saveItems(List<String> itemIds) {
List<String> notEmptyOfferIds = itemIds.stream()
.filter(itemId -> !itemId.isEmpty())
.collect(Collectors.toList());
// save in database
notEmptyOfferIds.forEach(eventPublisher::publish);
}
}

View File

@@ -0,0 +1,10 @@
package mocks;
public class LoggingEventPublisher implements EventPublisher {
@Override
public void publish(String addedOfferId) {
System.out.println("I've published: " + addedOfferId);
}
}

View File

@@ -0,0 +1,89 @@
import spock.lang.Specification
class FirstSpecification extends Specification {
def "one plus one should equal two"() {
expect:
1 + 1 == 2
}
def "two plus two should equal four"() {
given:
int left = 2
int right = 2
when:
int result = left + right
then:
result == 4
}
def "Should be able to remove from list"() {
given:
def list = [1, 2, 3, 4]
when:
list.remove(0)
then:
list == [2, 3, 4]
}
def "Should get an index out of bounds when removing a non-existent item"() {
given:
def list = [1, 2, 3, 4]
when:
list.remove(20)
then:
thrown(IndexOutOfBoundsException)
list.size() == 4
}
def "numbers to the power of two"(int a, int b, int c) {
expect:
Math.pow(a, b) == c
where:
a | b | c
1 | 2 | 1
2 | 2 | 4
3 | 2 | 9
}
def "Should return default value for mock"() {
given:
def paymentGateway = Mock(PaymentGateway)
when:
def result = paymentGateway.makePayment(12.99)
then:
!result
}
def "Should return true value for mock"() {
given:
def paymentGateway = Mock(PaymentGateway)
paymentGateway.makePayment(20) >> true
when:
def result = paymentGateway.makePayment(20)
then:
result
}
def "Should verify notify was called"() {
given:
def notifier = Mock(Notifier)
when:
notifier.notify('foo')
then:
1 * notifier.notify('foo')
}
}

View File

@@ -0,0 +1,3 @@
interface Notifier {
void notify(String message)
}

View File

@@ -0,0 +1,3 @@
interface PaymentGateway {
boolean makePayment(BigDecimal amount)
}

View File

@@ -0,0 +1,20 @@
package extensions
import spock.lang.Narrative
import spock.lang.Specification
import spock.lang.Title
@Title("""This title is easy to read for humans""")
class CustomTitleTest extends Specification {
}
@Narrative("""
as a user
i want to save favourite items
and then get the list of them
""")
class NarrativeDescriptionTest extends Specification {
}

View File

@@ -0,0 +1,22 @@
package extensions
import spock.lang.IgnoreIf
import spock.lang.Specification
class IgnoreIfTest extends Specification {
@IgnoreIf({System.getProperty("os.name").contains("windows")})
def "I won't run on windows"() {
expect:
true
}
@IgnoreIf({ os.isWindows() })
def "I'm using Spock helper classes to run only on windows"() {
expect:
true
}
}

View File

@@ -0,0 +1,16 @@
package extensions
import spock.lang.IgnoreRest
import spock.lang.Specification
class IgnoreRestTest extends Specification {
def "I won't run"() { }
@IgnoreRest
def 'I will run'() { }
def "I won't run too"() { }
}

View File

@@ -0,0 +1,20 @@
package extensions
import spock.lang.Ignore
import spock.lang.Specification
@Ignore
class IgnoreTest extends Specification {
@Ignore
def "I won't be executed"() {
expect:
true
}
def 'Example test'() {
expect:
true
}
}

View File

@@ -0,0 +1,25 @@
package extensions
import spock.lang.Issue
import spock.lang.Specification
class IssueTest extends Specification {
@Issue("http://jira.org/issues/LO-531")
def 'single issue'() {
}
@Issue(["http://jira.org/issues/LO-531", "http://jira.org/issues/LO-123"])
def 'multiple issues'() {
}
@Issue("LO-1000")
def "I'm using Spock configuration file"() {
expect:
true
}
}

View File

@@ -0,0 +1,11 @@
package extensions
import spock.lang.PendingFeature
class PendingFeatureTest {
@PendingFeature
def 'test for not implemented yet feature'() {
}
}

View File

@@ -0,0 +1,14 @@
package extensions
import spock.lang.Requires
import spock.lang.Specification
class RequiresTest extends Specification {
@Requires({ System.getProperty("os.name").contains("windows") })
def "I will run only on Windows"() {
expect:
true
}
}

View File

@@ -0,0 +1,18 @@
package extensions
import spock.lang.Specification
import spock.util.environment.RestoreSystemProperties
class RestoreSystemPropertiesTest extends Specification {
@RestoreSystemProperties
def 'all environment variables will be saved before execution and restored after tests'() {
given:
System.setProperty('os.name', 'Mac OS')
expect:
true
}
}

View File

@@ -0,0 +1,20 @@
package extensions
import spock.lang.Retry
import spock.lang.Specification
@Retry
class RetryTest extends Specification {
@Retry
def 'I will retry three times'() { }
@Retry(exceptions = [RuntimeException])
def 'I will retry only on RuntimeException'() { }
@Retry(condition = { failure.message.contains('error') })
def 'I will retry with a specific message'() { }
@Retry(delay = 1000)
def 'I will retry after 1000 millis'() { }
}

View File

@@ -0,0 +1,20 @@
package extensions
import spock.lang.See
import spock.lang.Specification
class SeeTest extends Specification {
@See("https://example.org")
def 'Look at the reference'() {
}
@See(["https://example.org/first", "https://example.org/first"])
def 'Look at the references'() {
}
}

View File

@@ -0,0 +1,13 @@
package extensions
import org.junit.Ignore
import spock.lang.Specification
class StackTraceTest extends Specification {
def 'stkacktrace'() {
// expect:
// throw new RuntimeException("blabla")
}
}

View File

@@ -0,0 +1,14 @@
package extensions
import spock.lang.Specification
import spock.lang.Stepwise
@Stepwise
class StepwiseTest extends Specification {
def 'I will run as first'() { }
def 'I will run as second'() { }
}

View File

@@ -0,0 +1,13 @@
package extensions
import mocks.ItemService
import spock.lang.Specification
import spock.lang.Subject
class SubjectTest extends Specification {
@Subject
ItemService itemService // initialization here...
}

View File

@@ -0,0 +1,24 @@
package extensions
import spock.lang.Specification
import spock.lang.Timeout
import java.util.concurrent.TimeUnit
@Timeout(5)
class TimeoutTest extends Specification {
@Timeout(1)
def 'I have one second to finish'() {
}
def 'I will have 5 seconds timeout'() {}
@Timeout(value = 200, unit = TimeUnit.SECONDS)
def 'I will fail after 200 millis'() {
expect:
true
}
}

View File

@@ -0,0 +1,131 @@
package mocks
import spock.lang.Specification
class ItemServiceUnitTest extends Specification {
ItemProvider itemProvider
ItemService itemService
EventPublisher eventPublisher
def setup() {
itemProvider = Stub(ItemProvider)
eventPublisher = Mock(EventPublisher)
itemService = new ItemService(itemProvider, eventPublisher)
}
def 'should return items sorted by name'() {
given:
def ids = ['offer-id', 'offer-id-2']
itemProvider.getItems(ids) >> [new Item('offer-id-2', 'Zname'), new Item('offer-id', 'Aname')]
when:
List<Item> items = itemService.getAllItemsSortedByName(ids)
then:
items.collect { it.name } == ['Aname', 'Zname']
}
def 'arguments constraints'() {
itemProvider.getItems(['offer-id'])
itemProvider.getItems(_) >> []
itemProvider.getItems(*_) >> []
itemProvider.getItems(!null) >> []
itemProvider.getItems({ it.size > 0 }) >> []
}
def 'should return different items on subsequent call'() {
given:
itemProvider.getItems(_) >>> [
[],
[new Item('1', 'name')],
[new Item('2', 'name')]
]
when: 'method is called for the first time'
List<Item> items = itemService.getAllItemsSortedByName(['not-important'])
then: 'empty list is returned'
items == []
when: 'method is called for the second time'
items = itemService.getAllItemsSortedByName(['not-important'])
then: 'item with id=1 is returned'
items == [new Item('1', 'name')]
when: 'method is called for the thirdtime'
items = itemService.getAllItemsSortedByName(['not-important'])
then: 'item with id=2 is returned'
items == [new Item('2', 'name')]
}
def 'should throw ExternalItemProviderException when ItemProvider fails'() {
given:
itemProvider.getItems(_) >> { new RuntimeException()}
when:
itemService.getAllItemsSortedByName([])
then:
thrown(ExternalItemProviderException)
}
def 'chaining response'() {
itemProvider.getItems(_) >>> { new RuntimeException() } >> new SocketTimeoutException() >> [new Item('id', 'name')]
}
def 'should return different items for different ids lists'() {
given:
def firstIds = ['first']
def secondIds = ['second']
itemProvider.getItems(firstIds) >> [new Item('first', 'Zname')]
itemProvider.getItems(secondIds) >> [new Item('second', 'Aname')]
when:
def firstItems = itemService.getAllItemsSortedByName(firstIds)
def secondItems = itemService.getAllItemsSortedByName(secondIds)
then:
firstItems.first().name == 'Zname'
secondItems.first().name == 'Aname'
}
def 'should publish events about new non-empty saved offers'() {
given:
def offerIds = ['', 'a', 'b']
when:
itemService.saveItems(offerIds)
then:
2 * eventPublisher.publish({ it != null && !it.isEmpty()})
}
def 'should return items'() {
given:
itemProvider = Mock(ItemProvider)
itemProvider.getItems(['item-id']) >> [new Item('item-id', 'name')]
itemService = new ItemService(itemProvider, eventPublisher)
when:
def items = itemService.getAllItemsSortedByName(['item-id'])
then:
items == [new Item('item-id', 'name')]
}
def 'should spy on EventPublisher method call'() {
given:
LoggingEventPublisher eventPublisher = Spy(LoggingEventPublisher)
itemService = new ItemService(itemProvider, eventPublisher)
when:
itemService.saveItems(['item-id'])
then:
1 * eventPublisher.publish('item-id')
}
}

View File

@@ -0,0 +1,30 @@
import extensions.TimeoutTest
import spock.lang.Issue
runner {
if (System.getenv("FILTER_STACKTRACE") == null) {
filterStackTrace false
}
report {
issueNamePrefix 'Bug '
issueUrlPrefix 'http://jira.org/issues/'
}
optimizeRunOrder true
// exclude TimeoutTest
// exclude {
// baseClass TimeoutTest
// annotation Issue
// }
report {
enabled true
logFileDir '.'
logFileName 'report.json'
logFileSuffix new Date().format('yyyy-MM-dd')
}
}