-
Notifications
You must be signed in to change notification settings - Fork 10
Initial setup
You are not limited to using the JetBrains Academy plugin when creating tests for a project (you can just create a regular IntelliJ IDEA project), but with the JetBrains Academy plugin, it may be more convenient.
To create a project with the JetBrains Academy plugin, you need to download IntelliJ IDEA. This version already contains the installed version of the JetBrains Academy plugin. If you already have a regular installation of IntelliJ IDEA installed, you can download the plugin from Marketplace.
After that, make sure you have enabled JetBrains Academy' project creating features:
- Click
Help
->Enable Course Creator Features
- Click
Ctrl + Shift + A
->Experimental features
-> check the box next toedu.course.hyperskill
To create a project, you need to click File -> Learn and Teach -> Create New Hyperskill Course
Set the title and click Create
. It does not matter if you choose Java
or Kotlin
since you'll later change build.gradle
file for the appropriate language.
This is how your project should look like for now. Please, don't touch .yaml
files - they are internal for the JetBrains Academy plugin.
Next, you need to delete lesson1
. You should end up with a single file build.gradle
. Replace the contents of this file with what is given below (in File templates
section).
Then, you should create a so-called Framework Lesson
and give it a name like a project name. For this, you need to create a new Lesson
and choose Framework lesson
in the dialog.
Then, you should create a new Task
inside this Framework Lesson
and give it the name stage1
. The task type should be Edu
.
Then remove src/Task.java
and test/Tests.java
, create package src/tictactoe
, create file src/tictactoe/Main.java
, create file test/TicTacToeTest.java
replace the contents of these files with what is given below (in File templates
section). Notice, that you need to name folder and file appropriately your project theme, don't stick to Tic-Tac-Toe. This is just an example. You should end up with this configuration:
To create tests for the second stage, click on Framework Lesson
named Tic-Tac-Toe
and add a new Task
. Name it stage2
. Your result should look like the following:
If you see (excluded)
near your files, please right-click on this file and click Course Creator
-> Include into Task
to include this file into the project.
Also, if you don't want some files to be seen by a user, you can hide them. It is especially useful when you're including tests into the project, and they are added as visible files by default, so you should hide them as well. In JetBrains Academy, hidden files are displayed in gray, and visible files are displayed in black.
You created an initial setup and ready to write tests!
After you finished creating your project, you need to upload it to Cogniterra. To do this, please click on a project name (the one with 4 squares, not to the one with a book), and click Course Creator
-> Upload Hyperskill Lesson to Cogniterra
.
To build a project, we use gralde
. You need to use Gradle version 8.5 and Java from 17 to 21. A typical project with several stages with Java/Kotlin/Scala tests looks like this:
Idea_project_folder
.idea
--Idea internal files--
build.gradle
settings.gradle
Project_name
| stage1
| | src
| | | user_package
| | | --user files--
| | test
| | --test files--
| stage2
| | src
| | | user_package
| | | --user files--
| | test
| | --test files--
| ...
| stageN
| | src
| | | user_package
| | | --user files--
| | test
| | --test files--
As you can see, the project is divided into stages. Each stage is a separate Gradle submodule and does not overlap with other stages in any way. The user_package
package is intended for the user to write his code to the project. The test
folder is intended for writing tests to the project stage.
So, the initial setup for writing tests for a Java/Kotlin/Scala project is as follows (let's say you're writing tests for the Tic-Tac-Toe project):
Idea_project_folder
build.gradle
settings.gradle
Tic-Tac-Toe
| stage1
| | src
| | | tictactoe
| | | Main.java / Main.kt / Main.scala
| | test
| | TicTacToeTest.java
The file Main.*
can contain some initial code for the student. They'll see it the first time they open the project. You can actually change the name of the class whenever you like, it can have any name, not just Main
. Usually, this file looks like this for a student when opening a project for the first time:
Main.java
package tictactoe;
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
Main.kt
package tictactoe
fun main() {
println("Hello World!")
}
Main.scala
package tictactoe
object Main extends App {
println("Hello, World!")
}
You shall implement the project stage in this file. Since you will have to check whether your tests work or not.
Below is an initial example of the TicTacToeTest.java/kt
file. Noice, that you don't need the user's class at all - the library will find the main method across all user's classes automatically.
Java
tests template
import org.hyperskill.hstest.dynamic.DynamicTest;
import org.hyperskill.hstest.stage.StageTest;
import org.hyperskill.hstest.testcase.CheckResult;
public class TicTacToeTest extends StageTest {
@DynamicTest
CheckResult test() {
return CheckResult.correct();
}
}
Kotlin
tests template
import org.hyperskill.hstest.dynamic.DynamicTest
import org.hyperskill.hstest.stage.StageTest
import org.hyperskill.hstest.testcase.CheckResult
class TicTacToeTest : StageTest<Any>() {
@DynamicTest
fun test(): CheckResult {
return CheckResult.correct()
}
}
Java, Kotlin, Scala projects can be tested using tests written in Java and Kotlin. Scala tests are not supported, you should write tests in Java or Kotlin to test Scala program.
Below are the build.gradle
and settings.gradle
files that you should use.
build.gradle
for Java projects
apply plugin: 'hyperskill'
subprojects {
apply plugin: 'application'
apply plugin: 'java'
def userJava = Integer.parseInt(JavaVersion.current().getMajorVersion())
def hsJava = Integer.parseInt(hs.java.version)
def testJava = Math.max(userJava, hsJava)
java.toolchain.languageVersion = JavaLanguageVersion.of(testJava)
compileJava {
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(userJava)
}
}
compileTestJava {
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(testJava)
}
}
repositories {
mavenCentral()
maven { url 'https://packages.jetbrains.team/maven/p/hyperskill-hs-test/maven' }
maven { url 'https://jitpack.io' }
}
dependencies {
testImplementation 'com.github.hyperskill:hs-test:release-SNAPSHOT'
}
configurations.all {
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
sourceSets {
main.java.srcDir 'src'
test.java.srcDir 'test'
}
test {
systemProperty "file.encoding", "utf-8"
outputs.upToDateWhen { false }
}
compileJava.options.encoding = 'utf-8'
tasks.withType(JavaCompile) {
options.encoding = 'utf-8'
}
}
project(':util') {
dependencies {
implementation 'com.github.hyperskill:hs-test:release-SNAPSHOT'
}
}
configure(subprojects.findAll {it.name != 'util'}) {
dependencies {
testImplementation project(':util').sourceSets.main.output
testImplementation project(':util').sourceSets.test.output
}
}
wrapper {
gradleVersion = hs.gradle.version
}
build.gradle
for Kotlin projects
buildscript {
apply plugin: 'hyperskill'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$hs.kotlin.version"
}
}
subprojects {
apply plugin: 'application'
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'hyperskill'
def userJava = Integer.parseInt(JavaVersion.current().getMajorVersion())
def hsJava = Integer.parseInt(hs.kotlin.javaVersion)
def testJava = Math.max(userJava, hsJava)
java.toolchain.languageVersion = JavaLanguageVersion.of(testJava)
compileJava {
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(userJava)
}
}
compileTestJava {
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(testJava)
}
}
repositories {
mavenCentral()
maven { url 'https://packages.jetbrains.team/maven/p/hyperskill-hs-test/maven' }
maven { url 'https://jitpack.io' }
}
dependencies {
testImplementation 'com.github.hyperskill:hs-test:release-SNAPSHOT'
}
configurations.all {
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
sourceSets {
main.java.srcDir 'src'
test.java.srcDir 'test'
}
test {
systemProperty "file.encoding", "utf-8"
outputs.upToDateWhen { false }
}
compileJava.options.encoding = 'utf-8'
tasks.withType(JavaCompile) {
options.encoding = 'utf-8'
}
}
project(':util') {
dependencies {
implementation 'com.github.hyperskill:hs-test:release-SNAPSHOT'
}
}
configure(subprojects.findAll {it.name != 'util'}) {
dependencies {
testImplementation project(':util').sourceSets.main.output
testImplementation project(':util').sourceSets.test.output
}
}
wrapper {
gradleVersion = hs.gradle.version
}
build.gradle
for Scala projects
buildscript {
repositories {
mavenCentral()
}
}
subprojects {
apply plugin: 'application'
apply plugin: 'scala'
apply plugin: 'java'
repositories {
mavenCentral()
maven { url 'https://packages.jetbrains.team/maven/p/hyperskill-hs-test/maven' }
maven { url "https://jitpack.io" }
}
dependencies {
implementation 'org.scala-lang:scala-library:2.12.7'
testImplementation 'com.github.hyperskill:hs-test:release-SNAPSHOT'
}
configurations.all {
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
sourceSets {
main.java.srcDir 'src'
main.scala.srcDir 'src'
test.java.srcDir 'test'
test.scala.srcDir 'test'
}
test {
systemProperty "file.encoding", "utf-8"
outputs.upToDateWhen { false }
}
compileJava.options.encoding = 'utf-8'
tasks.withType(JavaCompile) {
options.encoding = 'utf-8'
sourceCompatibility = 11
}
tasks.withType(ScalaCompile) {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
}
project(':util') {
dependencies {
implementation 'com.github.hyperskill:hs-test:release-SNAPSHOT'
}
}
configure(subprojects.findAll {it.name != 'util'}) {
dependencies {
testImplementation project(':util').sourceSets.main.output
testImplementation project(':util').sourceSets.test.output
}
}
wrapper {
gradleVersion = '7.1.1'
}
Notice dependency testImplementation 'com.github.hyperskill:hs-test:release-SNAPSHOT'
- it's this hs-test
library. This dependency points to the latest commit of the release
branch so the JetBrains Academy plugin will download relevant version of the library every time a user starts a project. The part configurations.all { resolutionStrategy.cacheChangingModulesFor 0, 'seconds' }
will ensure that Gradle will update the library on the user side after every commit to the release
immediately. If you want to use the latest features (or you're just trying to fix a bug) use master
branch. But keep in mind, that every project on Hyperskill uses release
branch.
Notice the usage of apply plugin: 'hyperskill'
and Java/Kotlin/Gradle version dependencies not hardcoded, but actually hidden behind variables hs.java.version
, java.gradle.version
e.t.c. They are defined in hs-gradle-plugin repo and are updated there so that we don't have to update every project on Hyperskill separately in case we want to update Java/Kotlin/Gradle.
Also, you should change default settings.gradle
generated by JetBrains Academy plugin. You can't see it when you generate new JetBrains Academy project, but it is actually there. To find it, change your project view from Course
to Project
and you will see settings.gradle
here in the project.
Here's settings.gradle
you should use in your project:
buildscript {
repositories {
maven { url 'https://packages.jetbrains.team/maven/p/hyperskill-hs-test/maven' }
maven { url 'https://jitpack.io' }
}
dependencies {
classpath "com.github.hyperskill:hs-gradle-plugin:release-SNAPSHOT"
}
configurations.all {
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
}
static String sanitizeName(String name) {
return name.replaceAll("[ /\\\\:<>\"?*|()]", "_").replaceAll("(^[.]+)|([.]+\$)", "")
}
rootProject.projectDir.eachDirRecurse {
if (!isTaskDir(it) || it.path.contains(".idea")) {
return
}
def taskRelativePath = rootDir.toPath().relativize(it.toPath())
def parts = []
for (name in taskRelativePath) {
parts.add(sanitizeName(name.toString()))
}
def moduleName = parts.join("-")
include "$moduleName"
project(":$moduleName").projectDir = it
}
def isTaskDir(File dir) {
return new File(dir, "src").exists() || new File(dir, "test").exists()
}
include 'util'
As you can see, in buildscript
block script imports hyperskill
plugin to be visible in build.gradle
. As with the hs-test
library, this dependency linked with hs-gradle-plugin repo and tied to the release
branch. So, whenever we want to update the dependencies in every project we just do 1 commit to this repository.
- Home
- About
- Initial setup
- Writing tests
- Guidelines for writing tests
- Outcomes of testing
- Generating and checking
- Presentation error
- Checking JSON
- Testing solutions written in different languages
- Creating Hyperskill problems based on hs-test
- Testing Java Swing applications
- Testing Java Spring applications
- Testing Ktor applications