[PYTHON] Ich habe einen visuellen Regressionstest auf GitHub Pages versucht

Motivation

Hallo @glassmonkey. Apropos Github Action, CI. Ich wollte etwas mit Bildern machen, wenn ich CI machen wollte, also versuchte ich einen einfachen visuellen Regressionstest. Ich habe es in Eile geschafft, daher würde ich mich über Ihre Meinungen und Eindrücke freuen.

Was ist ein visueller Regressionstest?

Die Erklärung im Blog von Astamuse war leicht zu verstehen, daher werde ich sie zitieren.

Der visuelle Regressionstest ist ein visueller Regressionstest, insbesondere ein Test, der einen Screenshot macht und den Unterschied extrahiert.

Mit anderen Worten, einen visuellen Regressionstest in der Umgebung von Github Action durchführen Das folgende Bild wird in der virtuellen Umgebung generiert.

In diesem Artikel

Wie hast du es gemacht?

Stichprobe

Die, die ich tatsächlich gemacht habe, sind wie folgt. https://github.com/glassmonkey/vue-sample/pull/3 Ich habe es dem Antrag hinzugefügt, den ich für das Studium von Vuejs gestellt habe.

Dieses Mal habe ich es mit einem Rechteck umgeben, damit die Änderungen wie unten gezeigt leicht zu verstehen sind.

Das Originalbild Bild nach Änderung Differenzbild
<img width="600px"# alt="Das Originalbild" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152938/136950cf-4133-b4c5-badb-6ed751650df1.png "> Geändertes Bild Differenzbild

Bedarf

https://github.com/glassmonkey/vue-sample/blob/master/.github/workflows/test.yml#L19-L20


BASE_URL: https://glassmonkey.github.io/vue-sample

DIFF_URL: http://localhost:8080

Inhalt testen

Testablauf

Das yml zum Testen ist wie folgt. https://github.com/glassmonkey/vue-sample/blob/master/.github/workflows/test.yml

name: test

on: pull_request
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1 # ①
      - name: develop run # ②
        run: |
          docker-compose up -d
      - name: run test # ③
        run: |
          cd tests && \
          docker-compose build && \
          docker-compose run app \
        env:
          WINDOW_SIZE: 1024,768
          BASE_URL: https://glassmonkey.github.io/vue-sample/
          DIFF_URL: http://localhost:8080
      - uses: jakejarvis/s3-sync-action@master # ④
        env:
          AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_REGION: 'ap-northeast-1'
          SOURCE_DIR: './tests/dist'
          DEST_DIR:  ${{github.repository}}/${{github.sha}}
      - name: post maessage # ⑤
        run: |
          cd tests && bash post.sh
        env:
          S3_PATH: https://${{ secrets.AWS_S3_BUCKET }}.s3-ap-northeast-1.amazonaws.com/${{github.repository}}/${{github.sha}}
          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

Die Anmeldeinformationen müssen wie folgt unter "Einstellungen> Geheimnisse" auf Github festgelegt werden. スクリーンショット 2019-12-02 12.30.20.png

Um es kurz zu erklären

  1. Initialisierung
  2. Erstellen Sie eine virtuelle Umgebung mit den Inhalten von PR
  3. Erstellen Sie einen Container für visuelle Regressionstests und führen Sie ihn aus
  4. Laden Sie das generierte Bild auf s3 hoch
  5. Senden Sie das Bild an PR

Es wird der Fluss von. Ich werde den Inhalt des Beitrags in 3 Bilderzeugung und 5 PR erklären.

Bilderzeugung

Die Aufnahme von Scoon-Aufnahmen und die Erzeugung von Differenzbildern werden unten durchgeführt. https://github.com/glassmonkey/vue-sample/blob/master/tests/src/main.py

Da der Container, der dieses Mal für den Test ausgeführt werden soll, unabhängig von der lokal erstellten Anwendung ist, kann der Name von localhost nicht aufgelöst werden, sodass ich ihn auf der Testseite unten zwangsweise neu geschrieben habe.

    if "localhost" in url: 
         host_addr = subprocess.run(["ip route | awk 'NR==1 {print $3}'"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).stdout.decode("utf8").rstrip('\n')
         url = url.replace("localhost", host_addr)

Über Screenshots

Ich habe auf den Artikel Ausführen von Selenium, Headless Chrome und Python 3 auf Docker verwiesen. Es ist zu beachten, dass die folgenden optionalen Elemente angepasst werden müssen. Besonders als ich mit kopflosem Chrom anfing, war ich ein wenig süchtig nach der Tatsache, dass es notwendig ist, die Fenstergröße zum Zeitpunkt des Startzeichens anzugeben.

   options.add_argument('--headless')
   options.add_argument('--no-sandbox')
   options.add_argument('--disable-dev-shm-usage')
   options.add_argument('--hide-scrollbars')
   options.add_argument('--window-size={}'.format(os.environ['WINDOW_SIZE']))

Dieses Mal habe ich die URL statisch als Screenshot erstellt, wie unten gezeigt, aber ich dachte, dass es in Ordnung wäre, sie von außen anzupassen, da Sie anscheinend auch das Dom-Element angeben können, das als Screenshot angezeigt werden soll.

    driver.get(url)
    driver.save_screenshot(filename)

Über Differenzbildgenerierung

Ich habe auf den Artikel [hier] verwiesen (https://www.pyimagesearch.com/2017/06/19/image-difference-with-opencv-and-python/). Ich versuche mit der folgenden Funktion ein Differenzbild des Screenshot-Bildes zu erzeugen.

def diff_images(base_image_path, diff_image_path):
    """
    referer to https://www.pyimagesearch.com/2017/06/19/image-difference-with-opencv-and-python/
    :param base_image_path:
    :param diff_image_path:
    :return:
    """
    # load the two input images
    base_image = cv2.imread(base_image_path)
    diff_image = cv2.imread(diff_image_path)

    # convert the images to grayscale
    grayA = cv2.cvtColor(base_image, cv2.COLOR_BGR2GRAY)
    grayB = cv2.cvtColor(diff_image, cv2.COLOR_BGR2GRAY)

    (score, sub) = compare_ssim(grayA, grayB, full=True)
    sub = (sub * 255).astype("uint8")
    print("SSIM: {}".format(score))
    thresh = cv2.threshold(sub, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
    cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)

    for c in cnts:
        # compute the bounding box of the contour and then draw the
        # bounding box on both input images to represent where the two
        # images differ
        (x, y, w, h) = cv2.boundingRect(c)
        cv2.rectangle(base_image, (x, y), (x + w, y + h), (0, 0, 255), 2)
        cv2.rectangle(diff_image, (x, y), (x + w, y + h), (0, 0, 255), 2)
    cv2.imwrite("/app/dist/base.png ", base_image)
    cv2.imwrite("/app/dist/diff.png ", diff_image)
    cv2.imwrite("/app/dist/sub.png ", sub)

POST an PR

https://github.com/glassmonkey/vue-sample/blob/master/tests/post.sh

Ich poste ein Bild, das über Api auf Github auf s3 hochgeladen wurde, mit Aktion zum Hochladen auf s3. Für die Verarbeitung habe ich auf [jessfraz / shaking-finger-action] verwiesen (https://github.com/jessfraz/shaking-finger-action/blob/master/add-comment.sh).

Ergebnis

Es wurde sicher auf diese PR fallen gelassen. https://github.com/glassmonkey/vue-sample/pull/3 スクリーンショット 2019-12-02 12.49.26.png

Zusammenfassung

Ich konnte einen einfachen visuellen Regressionstest durchführen. Da es sich um eine große Sache handelt, ist es möglicherweise möglich, sie als Aktion ordnungsgemäß in einem anderen Repository abzulegen. Ich hatte Api auf Github nicht richtig berührt, also war ich wirklich besorgt darüber, was ich mit dem Posten von Bildern anfangen sollte. Ich habe diesmal s3 gewählt, aber es kann einen anderen Ansatz geben. Ich habe aufgegeben, weil die Installation von Opencv kompliziert wird, aber ich habe den Testcontainer von alpine aufgegeben, weil er langsam ist, aber ich möchte ihn alpin machen.

Recommended Posts

Ich habe einen visuellen Regressionstest auf GitHub Pages versucht
Ich habe Kaokore, einen klassischen japanischen Datensatz, auf EfficientNet ausprobiert.
Ich habe MLflow auf Databricks ausprobiert
Ich habe versucht, eine Serverumgebung zu erstellen, die unter Windows 10 ausgeführt wird
Ich habe AdaNet gegen Tabellendaten ausprobiert
Ich habe versucht, einen einfachen Kredit-Score mit logistischer Regression zu erstellen.
Ich habe versucht, die COTOHA-API zu verwenden (es gibt auch Code auf GitHub).
Ich habe Cython unter Ubuntu auf VirtualBox ausprobiert
Ich habe versucht, einen Sender auf der IoT-Plattform "Rimotte" zu registrieren.
Ich habe versucht, MySQL auf einer virtuellen Linux-Maschine unter OCI Compute zu installieren
Ich habe versucht, Objekte mit YOLO v3 (TensorFlow 2.0) auf einer Windows-CPU zu erkennen!
Ich habe ein Systemkonfigurationsdiagramm mit Diagrams on Docker geschrieben
Ich habe versucht, das Ergebnis des A / B-Tests mit dem Chi-Quadrat-Test zu überprüfen
Ich habe eine multiple Regressionsanalyse mit Polypoly-Regression versucht
Ich habe versucht, einen Linebot zu erstellen (Vorbereitung)
Ich habe versucht, ○ ✕ mit TensorFlow zu spielen
Ich habe versucht, mit einer Schildkröte eine Linie zu ziehen
Ich habe versucht, Kivy in einer Mac-Umgebung zu installieren
Ich habe eine funktionale Sprache mit Python ausprobiert
Ich habe eine Web-API erstellt
Ich habe eine TensorFlow-Umgebung mit Windows 10 erstellt
So testen Sie auf einer von Django authentifizierten Seite
Ich habe versucht, pipenv zu verwenden, machen Sie sich also eine Notiz
Ich habe versucht, das Webanwendungs-Framework zu vergleichen
Ich habe versucht, ein Auto in 3D zu erkennen
Ich habe den ersten AI-Implementierungstest [Note A] bestanden und verschiedene Dinge ausprobiert
Ich habe das TensorFlow-Tutorial (MNIST für Anfänger) zur Cloud9-Klassifizierung handgeschriebener Bilder ausprobiert.
Ich habe versucht, einen Übersetzungs-BOT zu erstellen, der mit Discord unter Verwendung von Googletrans funktioniert
Ich habe versucht, eine Super-Resolution-Methode / ESPCN zu erstellen
Ich habe versucht, eine Super-Resolution-Methode / SRCNN build zu erstellen
Ich habe versucht, YOLO v3 mit Google Colab auszuführen
Ich möchte keinen Codierungstest machen
Ich habe versucht, jupyter nteract auf dem Heroku-Server zu starten
[Pythonocc] Ich habe versucht, CAD auf einem Jupyter-Notebook zu verwenden
Ich habe versucht, Pythonect, eine Programmiersprache für den Datenfluss, zu verwenden.
Ich habe versucht, eine CSV-Datei mit Python zu lesen
Ich habe versucht, eine zufällige Zeichenfolge zu generieren
Ich habe versucht, ein Python 3-Modul in C hinzuzufügen
Ich habe versucht, eine Super-Resolution-Methode / SRCNN build zu erstellen
Ich habe versucht, eine Super-Resolution-Methode / SRCNN build zu erstellen
Ich habe versucht, alembic auszuführen, ein Migrationstool für Python
Ich habe LINE Message API (line-bot-sdk-python) mit GAE ausprobiert
Erstellen Sie eine Python-Ausführungsumgebung unter IBM i
Ich habe versucht, die Datenbank (sqlite3) mit kivy zu verwenden
Ich habe versucht, mit tkinter mit dem Taschenrechner zu spielen
Automatischer Test von Pipenv + Pytest mit Github-Aktionen
Ich habe ein ○ ✕ Spiel mit TensorFlow gemacht
Ich habe ein wenig über die Klasse recherchiert
Der Typ, der gestolpert ist, als Pelican seinen Blog nicht auf Github-Seiten veröffentlichen konnte