gpt4 book ai didi

docker - 如果在Docker下运行的.NET Core单元测试的代码覆盖率不到90%,则打破TeamCity的构建

转载 作者:行者123 更新时间:2023-12-02 04:01:34 26 4
gpt4 key购买 nike

我最近一直在研究Docker,以及如何使用TeamCity在Docker容器中运行.NET Core单元测试,这是我的构建管道的一部分。我将此添加为Dockerfile的最后一行,以便能够运行测试:

ENTRYPOINT ["dotnet", "test", "--verbosity=normal"]

这些Dockerfile然后在TeamCity在命令行中使用docker-compose构建和运行的组合文件中引用。

我现在已经成功工作了。下一个挑战是,如果单元/集成测试的覆盖率小于90%(或其他值),则破坏构建。

我已成功使用coverlet.msbuild NuGet依赖关系来测量代码覆盖率,这是我构建的一部分。这在TeamCity中也能正常工作,我在TeamCity构建中看到了输出。

通过向每个测试项目中添加coverlet.msbuild并将Dockerfile入口点更改为:
ENTRYPOINT ["dotnet", "test", "--verbosity=normal", "/p:CollectCoverage=true", "/p:Threshold=90", "/p:ThresholdType=line"]

TeamCity的构建输出显示了包含结果的ASCII表,但是到目前为止,如果代码覆盖率不够高,我仍然找不到找到破坏该构建的好方法。如果代码覆盖率太低,TeamCity不会将构建留给自己的设备标记为失败,因为如果覆盖率太低,这是不合理的,就可以了!

我天真地以为我可以在TeamCity中创建一个失败条件,该条件将检测以下文本的存在:
'[Assemnbly]' has a line coverage '9.8%' below specified threshold '95%'

...使用这样的正则表达式:
has a line coverage '((\d+(\.\d*)?)|(\.\d+))%' below specified threshold '((\d+(\.\d*)?)|(\.\d+))%'

但是,当要测试的DLL引用单独测试的其他DLL时,就会变得棘手,因为Coverlet.msbuild报告了所有“接触”的DLL的覆盖率指标。例如,我有一个名为Steve.Core.Files.Tests的测试项目,用于测试Steve.Core.Files。但是,Steve.Core.Files依次引用Steve.Core.Extensions。我在自己的测试DLL中分别测试Steve.Core.Extensions,因此在测试文件时,我不在乎该DLL的结果。 TeamCity中的输出如下所示:
+-----------------------+--------+--------+--------+
| Module | Line | Branch | Method |
+-----------------------+--------+--------+--------+
| Steve.Core.Extensions | 23.5% | 40% | 40% |
+-----------------------+--------+--------+--------+
| Steve.Core.Files | 100% | 100% | 100% |
+-----------------------+--------+--------+--------+

...因此即使有问题的DLL是100%,它也会基于23.5%的位而失败。这实际上使检查使用Regex失败条件非常困难。

为了使事情更加复杂,出于两个原因,我正在使用单个动态Dockerfile运行所有程序集中的所有测试:
  • 我不想每次添加更多项目和测试时都必须更改Dockerfile和docker-compose文件(以及TeamCity)。
  • DLL之间有很多依赖关系,因此有必要一次构建它们并一起测试它们。

  • 这意味着我不愿意将测试分开,以便每个测试都有自己的Dockerfile-我知道这将使我能够使用Exclude / Include标志获得所需的行为。

    有谁有其他想法可以解决这个问题?

    我希望我可以在每个测试项目的级别添加一个文件,以告诉它要覆盖哪些DLL-那将是最好的解决方案。失败了,因为我在项目和测试项目之间使用了严格的命名约定,我可以在我的 dotnet test命令中添加一个开关来仅测试与测试程序集具有相同名称的程序集,最后减去.Tests位吗?

    提前致谢;帮助赞赏!

    干杯,

    史蒂夫。

    2018年9月7日更新:

    因此,我的Dockerfile现在特定于每个单元测试项目。它们看起来像这样,并存在于测试项目文件的旁边:
    FROM microsoft/dotnet:2-sdk

    # Set the working directory:
    WORKDIR /src

    # Copy the solution file and the NuGet.config across to the src directory:
    COPY *.sln NuGet.config ./

    # Copy the main source project files to the root level:
    COPY */*.csproj ./

    # Make directories for each project file and move the project file to the correct place:
    RUN for file in $(ls *.csproj); do mkdir -p ${file%.*}/ && mv $file ${file%.*}/; done

    # Restore dependencies:
    RUN dotnet restore

    # Copy all files so that we have all everything ready to compile:
    COPY . .

    # Set the flag to tell TeamCity that these are unit tests:
    ENV TEAMCITY_PROJECT_NAME = ${TEAMCITY_PROJECT_NAME}

    # Run the tests:
    ENTRYPOINT ["dotnet", "test", "Steve.Core.Configuration.Tests/Steve.Core.Configuration.Tests.csproj", "--verbosity=normal", "/p:CollectCoverage=true", "/p:Threshold=95", "/p:ThresholdType=line", "/p:Exclude=\"[Steve.Core.Testing]*\""]

    请注意,应该停止Steve.Core.Testing DLL的覆盖率结果的exclude开关将包含在Steve.Core.Configuration的结果中,这是测试的主要依赖项,并且正在对单元进行测试。

    我的撰写文件如下所示,并且位于解决方案文件旁边:
    version: '3.6'

    services:
    # Dependencies:
    steve.core.ldap.tests.ldap:
    image: osixia/openldap
    container_name: steve.core.ldap.tests.ldap
    environment:
    LDAP_ORGANISATION: Steve
    LDAP_DOMAIN: steve.com
    LDAP_ADMIN_PASSWORD: Password1
    steve.core.data.mysql.tests.database:
    image: mysql
    container_name: steve.core.data.mysql.tests.database
    command: mysqld --default-authentication-plugin=mysql_native_password
    environment:
    - MYSQL_ROOT_PASSWORD=Password1
    - MYSQL_DATABASE=testdb
    steve.core.data.sqlserver.tests.database:
    image: microsoft/mssql-server-linux
    container_name: steve.core.data.sqlserver.tests.database
    environment:
    - MSSQL_SA_PASSWORD=Password1
    - ACCEPT_EULA=Y
    - MSSQL_PID=Developer
    steve.core.email.tests.smtp:
    image: mailhog/mailhog
    container_name: steve.core.email.tests.smtp

    # Steve.Core.Configuration:
    steve.core.configuration.tests:
    image: steve.core.configuration.tests:tests
    build:
    context: .
    dockerfile: Steve.Core.Configuration.Tests/Dockerfile
    environment:
    - TEAMCITY_PROJECT_NAME

    # Steve.Core.Data.MySql:
    steve.core.data.mysql.tests:
    image: steve.core.data.mysql.tests:tests
    build:
    context: .
    dockerfile: Steve.Core.Data.MySql.Tests/Dockerfile
    environment:
    - TEAMCITY_PROJECT_NAME

    # Steve.Core.Data.SqlServer:
    steve.core.data.sqlserver.tests:
    image: steve.core.data.sqlserver.tests:tests
    build:
    context: .
    dockerfile: Steve.Core.Data.SqlServer.Tests/Dockerfile
    environment:
    - TEAMCITY_PROJECT_NAME

    # Steve.Core.Data:
    steve.core.data.tests:
    image: steve.core.data.tests:tests
    build:
    context: .
    dockerfile: Steve.Core.Data.Tests/Dockerfile
    environment:
    - TEAMCITY_PROJECT_NAME

    # Steve.Core.Email:
    steve.core.email.tests:
    image: steve.core.email.tests:tests
    build:
    context: .
    dockerfile: Steve.Core.Email.Tests/Dockerfile
    environment:
    - TEAMCITY_PROJECT_NAME

    # Steve.Core.Encryption:
    steve.core.encryption.tests:
    image: steve.core.encryption.tests:tests
    build:
    context: .
    dockerfile: Steve.Core.Encryption.Tests/Dockerfile
    environment:
    - TEAMCITY_PROJECT_NAME

    # Steve.Core.Execution:
    steve.core.execution.tests:
    image: steve.core.execution.tests:tests
    build:
    context: .
    dockerfile: Steve.Core.Execution.Tests/Dockerfile
    environment:
    - TEAMCITY_PROJECT_NAME

    # Steve.Core.Extensions:
    steve.core.extensions.tests:
    image: steve.core.extensions.tests:tests
    build:
    context: .
    dockerfile: Steve.Core.Extensions.Tests/Dockerfile
    environment:
    - TEAMCITY_PROJECT_NAME

    # Steve.Core.Files:
    steve.core.files.tests:
    image: steve.core.files.tests:tests
    build:
    context: .
    dockerfile: Steve.Core.Files.Tests/Dockerfile
    environment:
    - TEAMCITY_PROJECT_NAME

    # Steve.Core.Ldap:
    steve.core.ldap.tests:
    image: steve.core.ldap.tests:tests
    build:
    context: .
    dockerfile: Steve.Core.Ldap.Tests/Dockerfile
    environment:
    - TEAMCITY_PROJECT_NAME

    # Steve.Core.Maths:
    steve.core.maths.tests:
    image: steve.core.maths.tests:tests
    build:
    context: .
    dockerfile: Steve.Core.Maths.Tests/Dockerfile
    environment:
    - TEAMCITY_PROJECT_NAME

    # Steve.Core.Time:
    steve.core.time.tests:
    image: steve.core.time.tests:tests
    build:
    context: .
    dockerfile: Steve.Core.Time.Tests/Dockerfile
    environment:
    - TEAMCITY_PROJECT_NAME

    当它在TeamCity中运行时,即使在12个项目中有236个测试,它也仅报告来自两个项目的7个测试(出于某种奇怪的原因)。

    如果能帮上忙,我很乐意通过电子邮件将TeamCity构建的输出发送给我们。

    有谁知道我如何才能使我的测试全部重新运行?

    谢谢,

    史蒂夫。

    最佳答案

    因此,唯一的解决方案是将每个单元测试项目拆分为自己的撰写文件,该文件包括该测试DLL所需的依赖项。 (例如,用于测试电子邮件DLL的mailhog,用于测试数据库DLL的SQL Server等)。然后,TeamCity使用单个脚本分别运行它们,如下所示:

    docker-compose -f docker-compose-configuration-tests.yml up --force-recreate --abort-on-container-exit --build
    docker-compose -f docker-compose-configuration-tests.yml down --volumes --remove-orphans

    docker-compose -f docker-compose-data-mysql-tests.yml up --force-recreate --abort-on-container-exit --build
    docker-compose -f docker-compose-data-mysql-tests.yml down --volumes --remove-orphans

    ...

    每个人都有其自己的Dockerfile,该文件构建测试DLL并设置DLL异常以进行单元测试。 TeamCity在一个构建步骤中吐出所有测试的结果,上面我的问题中提到的regex代码覆盖失败情况,然后正确检测出未达到x%覆盖率的测试项目并中断了构建。

    现在要弄清楚如何将代码检查(例如FxCop和StyleCop的现代等效项)集成到我的构建过程中...

    关于docker - 如果在Docker下运行的.NET Core单元测试的代码覆盖率不到90%,则打破TeamCity的构建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52165797/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com