Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/arquillian/arquillian-spacelift-gradle

Gradle plugin to define complex testing scenarios via Spacelift
https://github.com/arquillian/arquillian-spacelift-gradle

Last synced: 3 days ago
JSON representation

Gradle plugin to define complex testing scenarios via Spacelift

Awesome Lists containing this project

README

        

= Arquillian Spacelift Gradle Plugin image:https://travis-ci.org/arquillian/arquillian-spacelift-gradle.svg["Build Status", link="https://travis-ci.org/arquillian/arquillian-spacelift-gradle"]

This Gradle plugin is able to prepare test environment and execute tests.
Plugin is using Arquillian Spacelift project to execute external commands. Compatible with Gradle 2.

In order to enable the plugin, define:

[source,groovy]
----
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "gradle.plugin.org.arquillian.spacelift.gradle:arquillian-spacelift-gradle:1.0.0-alpha-17"
}
}

apply plugin: "org.arquillian.spacelift"
----

Alternatively, you can use https://gradle.org/docs/current/userguide/plugins.html[incubating Gradle plugin DSL]:

[source,groovy]
----
plugins {
id "org.arquillian.spacelift" version "1.0.0-alpha-17"
}
----

== Spacelift Tasks

This plugin provides following tasks. You can get same info by running +./gradlew tasks+:

assemble::
Installs all installations defined by profile
check/test::
Executes tests defined in profile. Depends on +assemble+.
testreport::
Gathers all test results in JUnit format from workspace and creates a combined report. Requires additional configuration in _build.gradle_ file
describe::
Shows global configuration and available profiles and more
cleanCache::
Wipes cached installations and extracted installation artifacts for currently activated installations
cleanWorkspace::
Wipes Spacelift workspace directory
cleanRepository::
Wipes Maven repository used by Spacelift
cleanAll::
Executes all the +clean+ tasks

== DSL

Plugin uses following DSL structure:

[code,groovy]
----
spacelift {

workspace value
cacheDir value
killServers value

configuration {
item1 { }
}

tools {
tool1 { }
}

profiles {
profile1 { }
profile2(from:profile1) { }
}

installations {
installation1 { }
installation2(from:MyOwnInstallationType) { }
installation3(from:installation2) { }
}

tests {
test1 { }
}
}
----

value::
Value definition in accepted in following format. If it is defined in _block_, is is always lazy evaluated.
+
* _plain_ - such as +false+, +"mydir"+, +'mydir'+ or +"${project.rootDir}/mydir"+.
* _list_ - such as +"foo", "bar"+ or +[1, 2, 3]+
* _block_ - such as +{ false }+ or +{ /* a lot of code */ }+. Block does has access to properties of defining installation, profile, test or tool, whatever is relevant. It can also reference current project by using +project+ property
* _map_ - a map with keys denoting operating system and value either in _plain_ or _block_ form, for instance +[linux:"foo", windows: {"foo"}]+. Following OS values are supported:
** +linux+
** +windows+
** +mac+
** +solaris+
+

NOTE: If you are using a _map_, you need to use parenthesis around parameters

=== Spacelift configuration

Spacelift configuration can be modified by altering value of following properties:

* +workspace+ - a directory where you work, by default _`pwd`/ws_
* +installationsDir+ - a directory where installation files are cached, by default _~/.spacelift/cache_
* +killServers+ - {true|false} whether to kill Server processes first

=== User configuration

You can specify any configuration for your job in +configuration+ block in Spacelift DSL.
Also, you can provide a configuration in a specific profile, if you do so, it might override values in global configuration
block. That said, configuration is immutable in the script itself and the only way it can be changed is from command line.

[source,groovy]
----
configuration {
item1 {
type value
description value
converter value
defaultValue value
value value
}
...
}
----

A configuration item can have following values set:

type::
Type of the configuration item. This can be set to one of the built-in types or a custom one, but a converter needs to be provided. Built-in types: Boolean, Byte, Short, Integer, Long, CharSequence, String, Class, File. Default type is _String_.
description::
Description of the configuration item. This will be printed out when running the _describe_ task.
converter::
An instance of a ConfigurationItemConverter that will be used to convert the input from commandline into the type defined as well as converting the type back into string output.
defaultValue::
Default value that will be used when this configuration item is not input from commandline.
value::
If set, the configuration item cannot be changed from the commandline and is basically read-only.

=== User tools

Tools allow you to define Spacelift bindings for external commands that should be available on local system. Tools can be inherited from previously defined tools.

[source,groovy]
----
toolName {
command value
allowedExitCodes value
interaction value
isDaemon value
environment value
}
----

A tool can have following values set:

command::
Command defines what will be executed. In case you provide _string_ or _list of strings_, it will be transformed to
Spacelift +CommandBuilder+. In case you are using _block_, you are supposed to return +CommandBuilder+. In case of
map, you can use *windows*, *linux*, *mac* and *solaris* keys that will match the platform. The block will register a +CommandTool+
you can retrieve by +Spacelift.task('toolName')+ later on.
allowedExitCode::
Exit codes that command executing can return, by default +0+
interaction::
Interaction with the command process, by default +GradleSpaceliftDelegate.ECHO_OUTPUT+
isDaemon::
By default +false+. If set to +true+, tool will spawn a process that will survive Gradle execution exit.
environment::
By default +[:]+. Properties to be added to process environment.

=== User profiles

Profiles consist of installations to be installed and tests to be executed. You can use -P__profileName__ to trigger
specific profile, otherwise default profile is triggered. _default_ profile is expected to be present. Note, you need
define profileName quoted in case of _default_. Profiles can be inherited from previous created profiles.

[source,groovy]
----
profileName {
configuration { }
enabledInstallations 'installation1', 'installation2'
tests 'test1', 'test3', 'test27'
excludedTests 'test3'
}
----

Use the configuration block in profile to declare new configuration items or override those defined in the main _configuration_ block.

You can exclude tests from execution by _excludedTests_ on profile where you specify which tests you do not want to execute. By triggering the above profile, only _test1_ and _test27_ will be executed.

NOTE: You can also use +*+ to enable all defined installations and or tests for profile. And you can also use _value_ notion and construct a list of strings to match installation names.

=== User installations

Installations provides a way how to bring additional tools to you test environment. Installation is automatically downloaded
or fetched from local cache and extracted, based on current OS. Installations can be inherited from previously defined installations or you can
define your own installation DSL by implementing +Installation+ and point installation to its class.

[source,groovy]
----
installationName {
product value
version value
fileName value
remoteUrl value
home value
autoExtract value
isInstalled value
preconditions value
extractMapper { /* Any UncompressTool call(s) */ }
tools {
tool1 {
...
}
}
postActions {
}
}
otherInstallation(from:installationName) {
// reuses all values from installationName and then redefines home directory
home newValue
}
myInstallation(from:MyInstallationClass) {
// uses your own DSL, myBlock has to be a Closure typed property of MyInstallationClass
myBlock { }
}
----

Following DSL blocks are available for _DefaultInstallation_:

* product - name of product, used for storing installation in _installationsDir_
* version - version of product, used for storing installation in _installationsDir_
* fileName - name of file as downloaded in _workspace_. Can be map, same keys as for _tool_
* remoteUrl - URL where to download from. Can be map, same keys as for _tool_
* home - name of dir in _workspace_ where installation is extracted. Can be map, same keys as for _tool_
* autoExtract - by default +true+, consider installation an archive and extract it to _workspace_ directory
* isInstalled - by default check for installation _home_ existence, if evaluated to +true+, installation is skipped
* preconditions - this closure is optional and when specified, it has to return boolean value. If evaluated to +false+, installation is skipped, if +true+, installation is performed.
* extractMapper - optional calls on https://github.com/arquillian/arquillian-spacelift/blob/master/spacelift-impl/src/main/java/org/arquillian/spacelift/tool/basic/UncompressTool.java[UncompressTool] performed prior extraction happens. For instance, this removes first directory from extracted path and extracts archive to directory defined by +home+
+
[source]
----
extractMapper {
toDir(home)
cutdirs()
}
----
+
* tools - allows to define tool(s) that will be available after installation is done, same syntax as _tools_ block_
* postActions - defines actions to be performed after installation is extracted

=== User tests

Tests define a block of commands to be executed in *test* Gradle task. If you provide +dataProvider+ block, test execution (including before and after test phases) will iterate over data provided. Tests can inherit from previously defined tests or use your own DSL, same as +Installation+.

[source,groovy]
----
testName {
dataProvider {
// return an array here, allows to parametrize tests
}
beforeSuite {
// executed once prior all tests
}
beforeTest { value ->
// executed prior test
}
execute { value ->
// your commands here
}
afterTest { value ->
// executed after test
}
afterSuite {
// executed once prior all tests
}
}
----

== Referencing DSL elements in Gradle

In case you need, you can reference them directly in the code by its name. For instance, to reference home of installation named _selenium_ in your tests, you can use following syntax

[source,groovy]
----
installations {
selenium {
home "the-home"
}
}
tests {
testName {
execute {
assertThat selenium.home, is(notNullValue())
}
}
}
----

Direct reference can be used for any configuration item, installation, test, tool or profile. References are resolved in this order, in case there are two objects with different type and same name, further possible references are ignored and a warning is logged. It means it is safer to use unique names per all types.

NOTE: In case you need reference DSL object indirectly, for instance you have two objects with the same name or it is shaded by local variable, you can use indirect syntax in form +project.spacelift.installations['installationName']+. Similar call exists for configuration, tools, profiles and tests.

== Execution parameters

It is possible to modify what tests will be run and what installations will be installed. Apart from profile option, you can use:

[source,bash]
----
-Pinstallations=comma,separated,values
-Ptests=comma,separated,values
----

This will ignore installations and tests defined by profile and instead will install +comma+, +separated+ and +value+. If _test_ task is executed,
it will perform test execution for tests +comma+, +separated+ and +value+.

If you need to reference profile, installations or tests from a Gradle script, these are exposed as:

* +project.selectedProfile+
* +project.selectedInstallations+
* +project.selectedTests+

All represented by appropriate object.

=== Manual profile definitions

In cases you want to execute only a subset of installations or tests of given profile, you can combine activated profile with manual
override of installations and or tests.

For instance, following call installs all installations from *default* profile but executes only *myTestName* test.

[code,bash]
----
gradle -Pdefault -Ptests=myTestName test
----

Whereas this call completely ignores profile and installs *myTestNameRequirement* and then executes *myTestName*:

[code,bash]
----
gradle -Pinstallations=myTestNameRequirement -Ptests=myTestName test
----

NOTE: If you want to skip tests or installations altogether, use following syntax +gradle -Pinstallations= test+

== Spacelift Tools and Task

You can benefit from following tools and tasks, either from Spacelift itself or provided by this plugin:

* DownloadTool - downloads a file
* UnzipTool - extracts a zip file
* CommandTool - executes external command
* AntExecutor - executes Ant command. Requires _ant_ tool
* MavenExecutor - executes Maven command. Requires _mvn_ tool
* JavaExecutor - executes Java command. Requires _java_ tool
* XmlFileLoader - loads xml from file into +Node+
* XmlTextLoader - loads xml from text into +Node+
* XmlUpdater - stores +Node+ into file
* ArquillianXmlUpdater - updates container and/or extension properties in _arquillian.xml_ files
* PomXmlUpdater - updates properties in _pom.xml_ files
* SettingsXmlUpdater - updates _settings.xml_ with additional repositories, sets +localRepository+
* KillJavas - kills running Java processes (Selenium, JBoss AS/WildFly containers) and processes occupying ports
* StandaloneXmlUpdater - allows to add keystore/truststore configuration to _standalone.xml_
* DomainXmlUpdater - allows to add keystore/truststore configuration to _domain.xml_
* AndroidSdkUpdater - allows to fetch binaries for specific Android SDK target - you need to agree with Android SDK license first. Requires _android_ tool.
* AndroidSdkOptForStats - allows to opt out for stats - you need to agree with Android SDK license first
* AndroidEmulatorStarter - starts Android emulator
* AndroidEmulatorStopper - stops Android emulator
* AVDCreator - creates Android Virtual Devices
* CordovaExecutor - executes Cordova commands
* RHELVersion - determines version of RHEL system

== Release new version

Follow this process to release new version:

1. Update version to release version in _build.gradle_
2. Execute +gradle publishPlugins+ to publish plugin in Gradle Plugin Repository. Note that your _~/.gradle/gradle.properties_ should contain API key according to
https://plugins.gradle.org/docs/submit
3. Tag current commit via +git tag+
4. Bump version to next development version