There is a sample structure for kotlintest project - kotlin

I'm currently playing with the Kotlin testing Framework https://github.com/kotlintest/kotlintest.
I want to know if there is an expected way to structure the project, I mean, like a base project where I can start base on.

There is no specific way to structure the project just for this testing framework. You should structure it as any other Kotlin project, so your test should go to your-project/src/test/kotlin/com/jimmy/
The important thing is just to extend one of available base classes from kotlintest eg. WordSpec
You can see how it all (both structure and tests) looks like in kotlintest itself - https://github.com/kotlintest/kotlintest/tree/master/src/test/kotlin/io/kotlintest

There are some KotlinTest sample projects in the main repo here:
https://github.com/kotlintest/kotlintest/tree/master/kotlintest-samples
They use KotlinTest 3.0.x and for gradle users, the build file looks like:
apply plugin: 'org.junit.platform.gradle.plugin'
buildscript {
ext.kotlin_version = '1.2.31'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.junit.platform:junit-platform-gradle-plugin:1.1.0"
}
}
dependencies {
testCompile 'io.kotlintest:kotlintest-runner-junit5:3.0.3'
}
I won't include the Maven example as the pom.xml is verbose because it's XML, but you can find it in the above link.

You can test your code using spek, Here is the exaple, that might help to implement on your project.
Spek Test Example In Kotlin

Related

Can't add kotlinx to a fresh Kotlin/JS project

Trying to figure out what I'm doing wrong. I created a small video of exactly what I'm doing in IntelliJ on Windows.
https://www.youtube.com/watch?v=nIH_55Zbxus&feature=youtu.be
And I'll describe it here in text.
Create a new project
Tick the Gradle > Kotlin/JS for browser template and untick everything else
Add implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8' to the dependencies block in the build.gradle.
Sync the gradle files
Attempt to use something from the kotlinx.coroutines namespace
Hopefully its just a silly thing I'm missing. I expected to just have to add the coroutines library to be able to actually import it. It looks like the library is listed in the project structure for the main module so I'm not sure what else might be wrong. Here is a repo of the project too.
plugins {
id 'org.jetbrains.kotlin.js' version '1.3.72'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-js"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
testImplementation "org.jetbrains.kotlin:kotlin-test-js"
}
kotlin.target.browser { }
You should add kotlinx-coroutines-core-js dependency. See the documentation: https://github.com/Kotlin/kotlinx.coroutines#js

how to produce a 'fatjar' for a simple console application with gradle kotlin dsl

I have a simple app... but consider that even "hello world" would work as an example. I am building with gradle kotlin dsl.
I have applied the application plugin, and set mainClassName, but the only jar I get (in /build/libs) does not contain the libraries so cannot be simply run with "java filename". In fact, for some reason I still need to give it a main class as well.
But my real question, "what is what easiest way to produce the jar with libraries(fat jar) as an artifact?"
I would have thought the application plugin would have an option for that?
As #hotkey pointed out you can use the https://github.com/johnrengelman/shadow plugin like so:
In your depedencies and the following:
classpath 'com.github.jengelman.gradle.plugins:shadow:<version>'
Replace <version> with the current version.
And apply the plugin:
apply plugin: 'com.github.johnrengelman.shadow'
Then you are able to use the shadowJar task.
There are two options to do it with Gradle Kotlin DSL:
Build your own task.
An example is given in Gradle documentation
tasks.register<Jar>("uberJar") {
appendix = "uber"
from(sourceSets.main.get().output)
dependsOn(configurations.runtimeClasspath)
from({
configurations.runtimeClasspath.get().filter { it.name.endsWith("jar")}.map { zipTree(it) }
})
}
Use shadow plugin
plugins {
id("com.github.johnrengelman.shadow") version "4.0.4"
}
It will add shadowJar task, that can be invoked like this: gradle build shadowJar or gradle build shadowJar -x test to skip tests
It's often needed to include logging, which can be done like that:
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer
tasks.withType<ShadowJar> {
// the name of the file will be comprised of the basename and version, e.g. $baseName-$version.jar
baseName = "shadow"
transform(Log4j2PluginsCacheFileTransformer::class.java)
}

Proper structure for Gradle multi-module builds with IntelliJ IDEA

I have a Kotlin project which is comprised of three modules:
Core < Service < Web
The structure is:
build.gradle
core/
build.gradle
service/
build.gradle
web/
build.gradle
The structure for the root build.gradle file is:
buildscript {
ext.kotlin_version = '1.1.60'
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
subprojects {
apply plugin: 'kotlin'
apply plugin: 'jacoco'
compileKotlin {
kotlinOptions.jvmTarget = '1.8'
}
repositories {
mavenCentral()
jcenter()
}
}
The individual build files look like (for core):
dependencies {
// Kotlin
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
...
}
And for service (note the only difference is the project dependency):
dependencies {
compile project (':core')
// Kotlin
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
...
}
There are a few optimizations I'd like to make, but I'm still learning Gradle, and can't find the right way to reorganize things. The problems I have are:
I can't build service or web individually, as they complain about not being able to find their dependent sub-projects. (Via a gradle build in the service/ directory, for example.)
How can I define the Kotlin stdlib-jre8 dependency at the root level, so it's not duplicated in my three build files?
How can my subproject/buildscript tasks of the root buildfile use the same repository definitions, so that I don't have to define mavenCentral()/jcenter() twice?
Basically this build structure that I have was cobbled together through some experimentation/web resources, and happens to mostly work, but I'd like some guidance on doing it the right way, such that (1) it follows good Gradle practices, and (2) still works well via auto-import into IDEA.
If you want to run a build on a module you can do by running: gradle :web:build
In the same way that you are adding repositories in the subprojects clause, you can add the dependencies block in there. Make sure that only the shared dependencies are in there. For instance, compile project(':core') should only be in the relevant project. It's ok to have multiple dependency blocks. That said, it's usually more of a headache to use the subproject clause. Because, if dependencies change for one of the modules you are forced to update that for all of them
Regarding the repository definitions, they are very different. The one in the buildscript block is used by Gradle itself in order to find plugins and other 'pre-build' requirements. The one on the submodules is used to find the dependencies of the source code in the given module. As mentioned on the previous point, it's easier to manage when placed on the respective module build scripts.
Update:
If you want to keep the same version for all modules, the variables defined on ext in the buildscript should be able to be accessed from the submodules too: ext.kotlin_version = '1.1.60' and if you have multiple ones you can add them like:
ext {
kotlin_version = '1.1.60'
junit_version = '4.12'
}
Also, if you want to share code between modules, you can always extract it to gradle file and load it where needed using: apply file: "$rootDir/path/to/script.gradle"
Regarding #3, I'll give you a practical example.
Google has its own maven repository that contains all the dependencies for an android module. If you have a project that contains both a server-side module and android module you may not need the server-side one to look up dependencies on the Gradle artefact repository (artefact is the name of the jar dependency).
As for the buildscript repositories, in your case you are only loading one classpath (pre-build) dependency which is located on mavenCentral() so you may be ok removing jcenter() here.

Merging Android unit test and connected test code coverage data is broken

Version 2.3.3 of the Android Gradle Plugin was able to provide merged unit test and connected test code coverage data. In version 3.0.0, this capability is broken because each of the test types use a different and incompatible version of JaCoCo. Rafael Toledo provided a Medium blog post showing how to make this work with 2.3.3. I have provided a Github repo that illustrates the working code and the broken code in a few branches. The repo documentation provides a Readers Digest description of the problem. At this point I am convinced the Gradle Plugin team owns the issue and will file a bug shortly. My questions are:
1) Can anyone suggest a viable workaround? (there is a suggested fix by Carmen Alvarez posted to the Medium blog post but I get no joy from it.)
2) Can someone point me to instructions on how to hack and build the Gradle Android Plugin to test out a potential fix? (I found the answer to this one at http://tools.android.com/build/gradleplugin )
According to Android Plugin DSL Reference that contributes Android specific things:
To specify the version of JaCoCo you want to use, you now need to include it as a buildscript dependency in your project-level build.gradle file, as follows:
buildscript {
dependencies {
classpath "org.jacoco:org.jacoco.core:<jacoco-version>"
...
}
}
Previously Android Plugin had
android {
jacoco {
version = "<jacoco-version>"
}
}
According to Gradle JaCoCo Plugin documentation that contributes task of type JacocoReport:
The JaCoCo plugin adds a project extension named jacoco of type JacocoPluginExtension, which allows configuring defaults for JaCoCo usage in your build.
jacoco {
toolVersion = "<jacoco-version>"
}
And so here is modification for your https://github.com/pajato/acc that allows to align versions so that execution of ./gradlew clean jacocoTestReport succeeds:
buildscript {
dependencies {
classpath "org.jacoco:org.jacoco.core:0.7.9"
}
}
allprojects {
apply plugin: "jacoco"
jacoco {
toolVersion = "0.7.9"
}
}

IntelliJ, Android and Gradle

I am trying to get my existing Android Project working with gradle and IntelliJ 12.
Previously I had it working with maven but that didn't seem to be so flexible as gradle, and from what I think I got to know is that I need less subfolders.
My Android project is divided into a clean java library (:core) and the actual Application (:android). These two projects are both in my main project folder.
~-+MainProject
|--+core
| L--build.gradle
|--+android
| L--build.gradle
|--build.gradle
L--settings.gradle
I think the ideal solution to get gradle work with this is to treat the (:core) and (:android) project as nested projects, meaning I can simply be with my cmd in MainProject source folder to start the gradle tasks.
However I came up with different problems:
Gradle dependencies are only included in the core project
that means neither in the instrumentatetionTest nor in the main project files are any
directories correctly set as source / test directories
IntelliJ doesn't resolve any classes that I added as dependencies in gradle (AndroidSDK, junit, mockito, those from the :core project)
tried to use the plugin 'idea' but either I used it wrong or it didn't solve the problem
I get duplicate dependency Error for building the APK
must have something to do with junit:4.11 and mockito-core:1.9.5 that I added
what I tried:
deleting the dependencys -> build fails cause some classes of course could'nt be resolved
changing to junit:4.5+ as suggesed in some other thread -> no change at all
Here are the *.gradle configuartions
MainProject:
-- settings.gradle
include ':core', ':android'
-- build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.6.+'
}
}
subprojects {
repositories {
mavenLocal()
maven { url "http://repo.maven.apache.org/maven2" }
}
}
:core
-- build.gradle
apply plugin: 'java'
dependencies {
testCompile 'junit:junit:4.11'
testCompile 'org.mockito:mockito-core:1.9.5'
}
:android
apply plugin: 'android'
repositories {
mavenCentral()
}
dependencies {
compile project(":core")
compile 'com.google.android:android:4.1.1.4'
instrumentTestCompile 'junit:junit:4.11'
instrumentTestCompile 'org.mockito:mockito-core:1.9.5'
instrumentTestCompile 'com.google.dexmaker:dexmaker:1.0'
instrumentTestCompile 'com.google.dexmaker:dexmaker-mockito:1.0'
instrumentTestCompile 'com.jayway.android.robotium:robotium-solo:3.6'
}
/* ... androidSettings
I hope someone could help me with that
MFG Dornathal
Alright, so you've got the right idea, but there are a few changes you still need.
Your root build.gradle file should be as follows:
subprojects {
repositories {
mavenCentral()
}
}
You only need to include mavenLocal() if you are using a locally installed repo. Most people don't, and nothing in your project indicates that you need one.
mavenCentral() can be used to replace to maven URL you were using.
We only need to modify the buildscript for the android project, so we should localize that to the android project's build.gradle.
Your settings.gradle and your build.gradle for the core project are good.
Your build.gradle for the android project however, needs some changes:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.6.+'
}
}
apply plugin: 'android'
dependencies {
compile project(":core")
instrumentTestCompile 'com.jayway.android.robotium:robotium-solo:3.6'
}
By including the android plugin, we link directly to the installed SDK. This means we no longer need to include the android dependency: compile 'com.google.android:android:4.1.1.4'.
We don't need to include junit. It's provided by the SDK, so we'll just use that. One thing to note is that the SDK only includes JUnit 3.
We don't need to include mockito and dexmaker unless we actually use it for the android tests. If it's only being used for the tests on the java library, we don't need it here.
To answer your questions:
I'm not sure what you're asking here. It might help if you should your project structure including the directories in which you have files and such.
Your hunch is correct. Hamcrest, which provides matchers for tests, made a breaking change to their API between versions 1.1 and 1.3. JUnit 4.11 has a dependency on Hamcrest 1.3. Mockito 1.9.5 however, depends on Hamcrest 1.1. So when both are included, the 1.3 overrides the 1.1 & Mockito no longer works. Reverting to JUnit 4.5 is also a problem. Junit 4.5 includes the Hamcrest 1.1 jar as a file rather than as a dependency in the POM. So this will cause issues when we have 2 versions of the same file. JUnit 4.10 is the way you want to go here. This has the dependency on Hamcrest 1.1 and includes it in the POM instead of as a file. Win win! I've had issues with this too, and the best way for me to figure it out was to just look at the POM files on Maven Central and see what they tell me.
One final note. Intellij 12 cannot handle Gradle Multi-project builds. You need to switch to Android Studio or Intellij 13 for that.