为什么GitHub工作流中的PHPUnit生成的测试覆盖率XML报告与本地报告不同?

xvw2m8pv  于 2023-01-29  发布在  PHP
关注(0)|答案(2)|浏览(132)

我正在GitHub action for this PHP package中运行代码覆盖工作流,它生成的XML报告与我在本地运行PHPUnit测试时得到的报告不同,导致覆盖分数较低。
以下是工作流文件:

name: Update codecov

on:
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

permissions:
  contents: read

env:
  LANG: "sl_SI.utf8"

jobs:
  codecov:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3
        with:
          ref: ${{ github.head_ref }}

      - name: Set up system locale
        run: |
          sudo apt-get install -y locales
          sudo locale-gen ${{ env.LANG }}

      - name: Validate composer.json and composer.lock
        run: composer validate --strict

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: 7.2
          extensions: xdebug, gettext

      - name: Install dependencies
        run: composer update --prefer-dist --no-progress --prefer-stable

      - name: Run test suite
        run: vendor/bin/phpunit

      - name: Upload to Codecov
        uses: codecov/codecov-action@v2
        with:
          files: ./build/coverage.xml
          verbose: true

在本地,我得到:

<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="1673717717">
  <project timestamp="1673717717">
    <file name="/app/src/gettext-context.php">
      <line num="13" type="stmt" count="3"/>
      <line num="15" type="stmt" count="3"/>
      <line num="18" type="stmt" count="3"/>
      <line num="20" type="stmt" count="3"/>
      <line num="23" type="stmt" count="1"/>
      <line num="39" type="stmt" count="1"/>
      <line num="40" type="stmt" count="1"/>
      <line num="42" type="stmt" count="1"/>
      <line num="45" type="stmt" count="1"/>
      <line num="47" type="stmt" count="1"/>
      <line num="50" type="stmt" count="1"/>
      <line num="65" type="stmt" count="1"/>
      <line num="67" type="stmt" count="1"/>
      <line num="70" type="stmt" count="1"/>
      <line num="72" type="stmt" count="1"/>
      <line num="75" type="stmt" count="1"/>
      <line num="92" type="stmt" count="1"/>
      <line num="93" type="stmt" count="1"/>
      <line num="95" type="stmt" count="1"/>
      <line num="98" type="stmt" count="1"/>
      <line num="100" type="stmt" count="1"/>
      <line num="103" type="stmt" count="1"/>
      <metrics loc="105" ncloc="55" classes="0" methods="0" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="22" coveredstatements="22" elements="22" coveredelements="22"/>
    </file>
    <metrics files="1" loc="105" ncloc="55" classes="0" methods="0" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="22" coveredstatements="22" elements="22" coveredelements="22"/>
  </project>
</coverage>

但是,由工作流上载到www.example.com的XMLcodecov.io是:

<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="1673722112">
  <project timestamp="1673722112">
    <file name="/home/runner/work/gettext-context/gettext-context/src/gettext-context.php">
      <line num="3" type="stmt" count="0"/>
      <line num="13" type="stmt" count="3"/>
      <line num="15" type="stmt" count="3"/>
      <line num="18" type="stmt" count="3"/>
      <line num="20" type="stmt" count="3"/>
      <line num="23" type="stmt" count="1"/>
      <line num="27" type="stmt" count="0"/>
      <line num="39" type="stmt" count="1"/>
      <line num="40" type="stmt" count="1"/>
      <line num="42" type="stmt" count="1"/>
      <line num="45" type="stmt" count="1"/>
      <line num="47" type="stmt" count="1"/>
      <line num="50" type="stmt" count="1"/>
      <line num="54" type="stmt" count="0"/>
      <line num="65" type="stmt" count="1"/>
      <line num="67" type="stmt" count="1"/>
      <line num="70" type="stmt" count="1"/>
      <line num="72" type="stmt" count="1"/>
      <line num="75" type="stmt" count="1"/>
      <line num="79" type="stmt" count="0"/>
      <line num="92" type="stmt" count="1"/>
      <line num="93" type="stmt" count="1"/>
      <line num="95" type="stmt" count="1"/>
      <line num="98" type="stmt" count="1"/>
      <line num="100" type="stmt" count="1"/>
      <line num="103" type="stmt" count="1"/>
      <metrics loc="105" ncloc="55" classes="0" methods="0" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="26" coveredstatements="22" elements="26" coveredelements="22"/>
    </file>
    <metrics files="1" loc="105" ncloc="55" classes="0" methods="0" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="26" coveredstatements="22" elements="26" coveredelements="22"/>
  </project>
</coverage>

因为第二个包含了一些没有覆盖的行(例如<line num="3" type="stmt" count="0"/>),所以我的codecov结果是86%,而不是local中的100%。
问题中的行是source file中的if (function_exits('some_function'))语句,它们只是在声明函数之前Assert函数不存在。Here's它在codecov中的样子。
我不知道为什么XML报告不同。两个环境都运行相同的PHP版本和开发依赖项。phpunit.dist.xml文件对于两种情况是相同的,并且它被考虑,因为考虑到引导文件仅在phpunit.dist.xml文件中定义,否则测试将失败。

xzv2uavs

xzv2uavs1#

我完全明白发生了什么,但我解决了。我做了两件事:
1.使用here上的codecov PHP官方参考文章,我更新了我的工作流以匹配他们的工作流,并以如下方式结束:

name: Update codecov

on:
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

permissions:
  contents: read

env:
  LANG: "sl_SI.utf8"

jobs:
  codecov:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3
        with:
          ref: ${{ github.head_ref }}

      - name: Set up system locale
        run: |
          sudo apt-get install -y locales
          sudo locale-gen ${{ env.LANG }}

      - name: Install composer and dependencies
        uses: php-actions/composer@v6
        with:
          php_extensions: gettext

      - name: PHPUnit Tests
        uses: php-actions/phpunit@v3
        env:
          XDEBUG_MODE: coverage
        with:
          configuration: phpunit.xml.dist
          php_extensions: gettext xdebug
          args: --coverage-clover ./coverage.xml

      - name: Upload to Codecov
        uses: codecov/codecov-action@v2
        with:
          files: ./coverage.xml
          verbose: true

1.我将所有推荐的设置从php.ini移到phpunit.xml(.dist),因为很明显GH操作不会使用这些设置,除非在phpunit.xml中。

<php>
        <ini name="display_errors" value="On"/>
        <ini name="display_startup_errors" value="On"/>
        <!--
            PHPUnit recommended PHP config
            https://phpunit.readthedocs.io/en/9.5/installation.html#recommended-php-configuration
        -->
        <ini name="memory_limit" value="-1"/>
        <ini name="error_reporting" value="-1"/>
        <ini name="log_errors_max_len" value="0"/>
        <ini name="zend.assertions" value="1"/>
        <ini name="assert.exception" value="1"/>
        <ini name="xdebug.show_exception_trace" value="0"/>
    </php>

这修复了它,远程生成的三叶草XML文件与本地(dev)文件完全匹配。因此,我能够实现100%的覆盖率:)

vyswwuz2

vyswwuz22#

感谢您清晰的用例(测试中的库是一个文件)以及写得很好的问题,可以回答代码覆盖率 * 如何 * 不同:

  • 如果在收集代码覆盖率之前已经定义了函数,并且是从不同的文件(不是测试中的文件)定义的,那么函数的实际行就不会被覆盖。
  • 如果函数是未定义的,那么它们将被代码覆盖覆盖,而不仅仅是它们的if子句。

尽管这在回答中说得很清楚,但我们也可能倾向于问“为什么"会这样,然而你的问题显示的信息太少,这样做会倾向于猜测。
然而,据我所知,不同的代码覆盖机制并不能解释这种差异,例如xdebug与pcov,这是导致不同覆盖率的另一个常见原因,但在更详细的层面上。它也不是xdebug 2与xdebug 3,因为您使用的PHP 7.2只有xdebug 2(顺便说一句,PHP版本与您销售的软件包相冲突:〉= 7.4 -显然这不是一个要求,而是虚假的[不是一个道德判断])。
我建议您在自动化测试中仔细检查需求,这样您就不会盲目地运行整个测试套件,而只是在稍后的覆盖中发现,您期望覆盖的代码根本没有覆盖(虽然测试套件报告的不同,也倾向于虚假[又不是道德判断,这可以通过Assertbootstrap.php中require_once调用的返回值来完成,然后运行phpunit并激活phpAssert并抛出(建议在PHP 7.0+中运行PHP进行测试)。

相关问题