t.me/atinfo_chat Telegram группа по автоматизации тестирования

Различия в запуске тестов в docker и просто на машине

Теги: #<Tag:0x00007f74974663c0> #<Tag:0x00007f74974662a8> #<Tag:0x00007f7497466078> #<Tag:0x00007f7497465fb0> #<Tag:0x00007f7497465d30>

Всем привет.
Не могу никак отловить проблему. Дано:

  • Тестовый проект на gradle.
  • Docker.

Тестовый проект разбит на несколько модулей с тестами.
На обычных машинах (вне докера всё запускается).
После запаковки проекта в контейнер и запуска точно такой же команды. В контейнере запускается только несколько тестов. Причём в логах о тестах которые не запускались нет ни слова.
Используем официальные gradle контейнеры . Пробовал разные версии, результат одинаковый.

Не знаю уже в какую сторону копать, в каком случае в принципе gradle может при одинаковой строке запуска не выполнять часть тестов?

Вы хотя бы команду прислали, как запускаете, что за docker? Хоть какие-то вводные данные

1 Симпатия

Команда стандартная gradle -DENV=test :<module>:test --info
Что такое Docker? Образ какой? Например, gradle:6.3.0-jdk8.

Docker - это ПО, которое позволяет разворачивать контейнеры на основе образов. По другому виртуализация, которая использует ресурсы ОС.
У меня крутится Jenkins в Docker’е и все тесты на gradle запускаются.
Я запускаю ./gradlew clean test

Мой build.gradle

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath "io.qameta.allure:allure-gradle:2.8.1"
        classpath "org.junit.platform:junit-platform-gradle-plugin:1.2.0"
    }
}

plugins {
    id 'java'
    id 'idea'
}

group 'chat.ros.testing2.webclient'
version '1.0'

compileJava.options.encoding = 'UTF-8'
compileTestJava.options.encoding = 'UTF-8'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
    mavenLocal()
}

dependencies {
    // https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api
    testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.6.0'
    // https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine
    testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.6.0'
    // https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params
    testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: '5.6.0'
    // https://mvnrepository.com/artifact/org.junit/junit5-engine
    compile group: 'org.junit', name: 'junit5-engine', version: '5.0.0-ALPHA'

    //dependencies for selenium
    // https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java
    compile group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '3.141.59'
    // https://mvnrepository.com/artifact/com.codeborne/selenide
    compile group: 'com.codeborne', name: 'selenide', version: '5.4.1'
    // https://mvnrepository.com/artifact/ru.stqa.selenium/webdriver-factory
    compile group: 'ru.stqa.selenium', name: 'webdriver-factory', version: '4.3'

    //dependencies for reporting
    // https://mvnrepository.com/artifact/io.qameta.allure/allure-junit5
    testCompile group: 'io.qameta.allure', name: 'allure-junit5', version: '2.13.1'
    // https://mvnrepository.com/artifact/io.qameta.allure/allure-junit-platform
    compile group: 'io.qameta.allure', name: 'allure-junit-platform', version: '2.13.1'
    // https://mvnrepository.com/artifact/io.qameta.allure/allure-selenide
    compile group: 'io.qameta.allure', name: 'allure-selenide', version: '2.13.1'
    // https://mvnrepository.com/artifact/ru.yandex.qatools.ashot/ashot
    compile group: 'ru.yandex.qatools.ashot', name: 'ashot', version: '1.5.4'
    // https://mvnrepository.com/artifact/org.slf4j/slf4j-api
    compile group: 'org.slf4j', name: 'slf4j-api', version: '2.0.0-alpha1'
    // https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12
    testCompile group: 'org.slf4j', name: 'slf4j-log4j12', version: '2.0.0-alpha1'

    //Dependencies for connect ssh
    // https://mvnrepository.com/artifact/com.jcraft/jsch
    compile group: 'com.jcraft', name: 'jsch', version: '0.1.55'

    compile 'io.socket:socket.io-client:0.8.3'

    //local library
    compile fileTree(dir: 'libs', include: '*.jar')
}

apply plugin: 'io.qameta.allure'
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'idea'

allure {
    version = '2.8.1'
    autoconfigure = true
    aspectjweaver = true

    downloadLink = 'https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/2.8.1/allure-commandline-2.8.1.zip'

    useJUnit5 {
        version = '2.13.1'
    }
}

test {

    useJUnitPlatform()

    dependsOn 'cleanTest'

    // Show test results.
    testLogging {
        events "passed", "skipped", "failed"
    }
}

а сами тесты которые не стартуют есть внутри контейнера?

1 Симпатия

Да, есть. Их можно спокойно запустить через ключ --tests. Но когда запускаются все тесты из модуля. То запускается только тесты из парочки классов. Без докера запускаются все.

Ну наверно, эти классы не находятся запускальщиком тестового фрейморка.
Я бы после залития их в образ, на папку tests и всё внутри её, права бы раздал на нужного пользователя sudo chown -R user:user tests

Да нет. Права на все файлы одинаковы. К тому же говорю, что если запускать напрямую через опцию --tests, то запускается.

Причём в контейнере запуск и напрямую через gradle и через wrapper gradlew работают с одинаковым результатом.

Ещё заметил, что если запускать не внутри контейнера, а через команду docker run --rm -u gradle -v <путь до проекта>:/home/gradle/project -w /home/gradle/project gradle gradle -DENV=stg :<module>:test --info то опять же тесты проходят все.

McStarМаксим Таран сможете минмальный битый проект расшарить ? продемонстрировать другим ? тесты кот не выполнябтся можно сделать dummy так ведь ?

Это не проект битый, это как-то в докере не так. Расшарить не могу. Он здоровый. :slight_smile: Заколебусь менять. Проект старый, просто теперь девопсы решили запихнуть всё в кубер. Ну не получилось. Начал я смотреть как автор. И тоже не понимаю, что происходит.
Более того, даже смотрю логирование отличается. Например в докере нет логирования событий типа “started”, “skiped”. И у нас есть фильтр для логера для некоторых тестов он тоже не работает. То ли классов не находит то ли ещё что. Но непонятно почему тогда через --tests всё работает.
Я прост опока гипотетически не могу предположить в каком случае в принципе может различаться поведение. Никогда с докером не работал. Вот думал, может сталкивался кто.

Вот мой основной build.gradle.kts

build.gradle.kts
import io.qameta.allure.gradle.task.AllureReport
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("io.qameta.allure") version "2.8.1"
    kotlin("jvm") version "1.3.71"
}

val kotlinVersion by ext("1.3.71")
val protobufVersion by ext("3.9.0")
val junitVersion by ext("5.6.0")
val allureVersion by ext("2.13.1")
val exposedVersion by ext("0.21.1")
val e = System.getProperty("ENV", "")
val reportPath = System.getProperty("REPORTPATH", "$rootDir/allure")

allure {
    version = allureVersion
    clean = true
    downloadLink =
        "https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/$allureVersion/allure-commandline-${allureVersion}.zip"
    reportDir = file("$reportPath/$e/allure-report")
    resultsDir = file("$reportPath/$e/allure-results")
}

allprojects {
    group = "some.group"
    version = "1.0-SNAPSHOT"

    repositories {
        jcenter()
        mavenCentral()
        maven(url = "https://plugins.gradle.org/m2/")
    }
}

val testingModules = listOf("dummy-tests", "dummy2-tests", "dummy3-tests")

subprojects {
    apply(plugin = "idea")
    apply(plugin = "org.jetbrains.kotlin.jvm")
    java {
        sourceCompatibility = JavaVersion.VERSION_1_8
    }

    dependencies {
        implementation(kotlin("stdlib-jdk8"))
        implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
        implementation("io.github.microutils:kotlin-logging:1.6.22")
        implementation("org.slf4j:slf4j-api:1.7.25")
        implementation("ch.qos.logback:logback-classic:1.2.3")
        implementation("com.github.salomonbrys.kotson:kotson:2.5.0")
        implementation("com.natpryce:konfig:1.6.10.0")
    }

    tasks.withType<KotlinCompile> {
        kotlinOptions.jvmTarget = "1.8"
    }
    // all testing modules
    if (testingModules.contains(name)) {
        apply(plugin = "io.qameta.allure")
    }
}

configure(subprojects.filter { testingModules.contains(it.name) || it.name == "common" }) {
    dependencies {
        implementation("io.rest-assured:kotlin-extensions:4.2.0")
        implementation("io.qameta.allure:allure-rest-assured:$allureVersion")
        implementation("com.microsoft.sqlserver:mssql-jdbc:7.2.2.jre8")
        implementation("org.jetbrains.exposed:exposed-core:$exposedVersion")
        implementation("org.jetbrains.exposed:exposed-java-time:$exposedVersion")
        implementation("org.jetbrains.exposed:exposed-jdbc:$exposedVersion")
        implementation("org.jetbrains.exposed:exposed-dao:$exposedVersion")
    }
}

configure(subprojects.filter { testingModules.contains(it.name) || it.name == "emulator" }) {
    dependencies {
        implementation("com.google.protobuf:protobuf-java:$protobufVersion")
        implementation("com.google.code.gson:gson:2.8.5")
        implementation("org.apache.avro:avro:1.8.2")
        implementation("com.microsoft.azure.sdk.iot:iot-device-client:1.17.5")
    }
}

configure(subprojects.filter { testingModules.contains(it.name) }) {
    dependencies {
        implementation(project(":common"))
        if (project.name == "dummy-tests")
            implementation("com.sun.mail:javax.mail:1.6.2")

        testImplementation("org.junit.jupiter:junit-jupiter-api:$junitVersion")
        testImplementation("org.junit.jupiter:junit-jupiter-params:$junitVersion")
        testImplementation("org.assertj:assertj-core:3.15.0")

        testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$junitVersion")
    }

    tasks.withType<Test> {
        onlyIf { e.isNotBlank() }
        beforeTest(KotlinClosure1<TestDescriptor, Any>({
            println("""Environments before running "${this.name}" test:""")
            systemProperties.forEach {
                println("${it.key}=${it.value}")
            }
        }))
        useJUnitPlatform { }
        reports.html.isEnabled = false
        systemProperties = System.getProperties().mapKeys { it.key.toString() }
        systemProperties["ENV"] = e.removePrefix("cvp-")
        systemProperties.remove("java.endorsed.dirs")
//        maxHeapSize = "2g"
        logging.captureStandardOutput(LogLevel.DEBUG)
        /* testLogging {
             showStandardStreams = true
             events(PASSED, SKIPPED, FAILED, STARTED)
 //            showExceptions = true
 //            exceptionFormat = FULL
 //            showCauses = true
 //            showStackTraces = true
         }*/
    }

    allure {
        autoconfigure = true
        version = allureVersion
        useJUnit5 { version = allureVersion }
        clean = true
        resultsDir = file("$reportPath/$e/allure-results")
    }
}

tasks.withType<Wrapper> {
    distributionType = Wrapper.DistributionType.ALL
    gradleVersion = "6.1.1"
}

tasks {
    register<WriteProperties>("createEnvFile") {
        property("Environment", e)
        outputFile = File("$reportPath/$e/allure-results/environment.properties")
    }
}

tasks.register<AllureReport>("allureAggregatedReport") {
    onlyIf { e.isNotBlank() }
    dependsOn("createEnvFile")
    copy {
        from("$reportPath/$e/allure-report/history")
        into("$reportPath/$e/allure-results/history")
    }
}

Закоментаренные строчки - это я просто по-разному логировать уже пробовал. beforeTest тоже перестал выполняться, почему-то.

Кажется разобрался. Проблема в памяти. В контейнере её выделяется мало.