LoginSignup
0
0

More than 1 year has passed since last update.

PHPUnitのカバレッジバッジを作成する

Last updated at Posted at 2023-01-18

バッジを表示

![](https://coverage.deno.dev/hoge.svg)

バッジを更新

最後の数字を変更することで更新できます。/hoge.svgなどのパスは好きなのいれてください
https://coverage.deno.dev/hoge.svg?97

CI/CDに組み込む場合

vendor/bin/phpunit --coverage-html reports
# for Laravel
# php artisan test --coverage-html reports

percentage=$(printf %.0f $(grep -Pom1 '(?<=aria-valuenow=").*?(?=")' reports/index.html))
curl https://coverage.deno.dev/hoge.svg?$percentage

ソースコード

https://dash.deno.com/_api/projects/ のAPIで環境変数を更新できます。

import { serve } from "https://deno.land/std@0.155.0/http/server.ts";

const seeds = {
    width: [107, 3, 4],
    cwidth: [29, 3, 4],
    x: [915, 15, 20],
    textLength: [190, 30, 40]
}
const calc = (p, s) => [s[0], s[1]*2, s[1]*2].slice(0, p.length).reduce((a, b) => a+b)
const thresholds = [97, 93, 80, 65, 45, 15, 0];
const colors = [1217, 9947648, 10790429, 14660375, 16678199, 14703940, 10461087].map(i => i.toString(16));

function generateBadge(p) {
  const width = calc(p, seeds.width)
  const cwidth = calc(p, seeds.cwidth)
  const x = calc(p, seeds.x)
  const textLength = calc(p, seeds.textLength)
  const color = colors[thresholds.findIndex(i => p >= i)]

  return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${width}" height="20" role="img" aria-label="coverage: ${p}%"><title>coverage: ${p}%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="${width}" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="78" height="20" fill="#555"/><rect x="78" width="${cwidth}" height="20" fill="#${color}"/><rect width="${width}" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZXNtb2tlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+R2l0SHViPC90aXRsZT48cGF0aCBkPSJNMTIgLjI5N2MtNi42MyAwLTEyIDUuMzczLTEyIDEyIDAgNS4zMDMgMy40MzggOS44IDguMjA1IDExLjM4NS42LjExMy44Mi0uMjU4LjgyLS41NzcgMC0uMjg1LS4wMS0xLjA0LS4wMTUtMi4wNC0zLjMzOC43MjQtNC4wNDItMS42MS00LjA0Mi0xLjYxQzQuNDIyIDE4LjA3IDMuNjMzIDE3LjcgMy42MzMgMTcuN2MtMS4wODctLjc0NC4wODQtLjcyOS4wODQtLjcyOSAxLjIwNS4wODQgMS44MzggMS4yMzYgMS44MzggMS4yMzYgMS4wNyAxLjgzNSAyLjgwOSAxLjMwNSAzLjQ5NS45OTguMTA4LS43NzYuNDE3LTEuMzA1Ljc2LTEuNjA1LTIuNjY1LS4zLTUuNDY2LTEuMzMyLTUuNDY2LTUuOTMgMC0xLjMxLjQ2NS0yLjM4IDEuMjM1LTMuMjItLjEzNS0uMzAzLS41NC0xLjUyMy4xMDUtMy4xNzYgMCAwIDEuMDA1LS4zMjIgMy4zIDEuMjMuOTYtLjI2NyAxLjk4LS4zOTkgMy0uNDA1IDEuMDIuMDA2IDIuMDQuMTM4IDMgLjQwNSAyLjI4LTEuNTUyIDMuMjg1LTEuMjMgMy4yODUtMS4yMy42NDUgMS42NTMuMjQgMi44NzMuMTIgMy4xNzYuNzY1Ljg0IDEuMjMgMS45MSAxLjIzIDMuMjIgMCA0LjYxLTIuODA1IDUuNjI1LTUuNDc1IDUuOTIuNDIuMzYuODEgMS4wOTYuODEgMi4yMiAwIDEuNjA2LS4wMTUgMi44OTYtLjAxNSAzLjI4NiAwIC4zMTUuMjEuNjkuODI1LjU3QzIwLjU2NSAyMi4wOTIgMjQgMTcuNTkyIDI0IDEyLjI5N2MwLTYuNjI3LTUuMzczLTEyLTEyLTEyIi8+PC9zdmc+"/><text aria-hidden="true" x="485" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="510">coverage</text><text x="485" y="140" transform="scale(.1)" fill="#fff" textLength="510">coverage</text><text aria-hidden="true" x="${x}" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="${textLength}">${p}%</text><text x="${x}" y="140" transform="scale(.1)" fill="#fff" textLength="${textLength}">${p}%</text></g></svg>`
}

serve(async (req: Request) => {
  const url = new URL(req.url)
  const p = url.search.slice(1) || Deno.env.get(url.pathname) || '0'
  if (url.search) {
    fetch('https://dash.deno.com/_api/projects/coverage/env', {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/json',
        'cookie': 'token=' + ACCESS_TOKEN
      },
      body: JSON.stringify({[url.pathname]: p})
    })
  }
  return new Response(generateBadge(p), {
    headers: {
      'content-type': 'image/svg+xml; charset=utf-8',
      'cache-control': 'private, no-store, no-cache, must-revalidate',
      'pragma': 'no-cache'
    },
  });
});
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0