Playwrightで遷移先ページのタイトルを評価しようとしたら成功したり失敗したりした

起こったこと

Playwrightで遷移先ページのタイトルを評価しようとしたら成功したり失敗したりとフレイキーなテストになってしまった。

Version

    "@playwright/test": "^1.28.1"

コード

対象HTML

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>test</title>
</head>

<body>
  <main>
    <a href="https://ja.wikipedia.org/wiki/%E5%8F%8D%E5%B0%84%E6%98%9F%E9%9B%B2" target="_blank">反射星雲</a>
  </main>
</body>

</html>

Playwrightでは

import { test, expect } from "@playwright/test";

// baseUrlはlocalhostが設定されている
test("Wikipediaへ別タブで遷移する", async ({ page }) => {
  await page.goto("/link.html");
  const [page1] = await Promise.all([
    page.waitForEvent("popup"),
    page.getByRole("link", { name: "反射星雲" }).click(),
  ]);
  expect(await page1.title()).toBe("反射星雲 - Wikipedia");
});

たまにfailする

こうした

DOMがロードされるのを待つようにした

import { test, expect } from "@playwright/test";

// baseUrlはlocalhostが設定されている
test("Wikipediaへ別タブで遷移する", async ({ page }) => {
  await page.goto("/link.html");
  const [page1] = await Promise.all([
    page.waitForEvent("popup"),
    page.getByRole("link", { name: "反射星雲" }).click(),
  ]);
  await page.waitForLoadState("domcontentloaded"); // ここを追加
  expect(await page1.title()).toBe("反射星雲 - Wikipedia");
});

安定するようになった。気がする。たまたまフレイキーなテストが成功し続けているだけかもしれない。

Playwrightで新規ページのURLをアサートしたい

起こったこと

Playwrightでページ遷移のテストは書けるが、新規ページで開かれるURLのアサートの仕方がわからない。

version

@playwright/test: "^1.28.1"

コード

test("foobartest", await ({ page, context }) =>{
  const [newPage, _] = await Promise.all([
    context.waitForEvent('page'),
    page.getByLabel("TEXT"),
  ])
  await expect(newPage).toHaveURL("URL_OR_PATH");
});

JavascriptでBasic認証のついたURLから認証情報だけ消したURLを取得したい

起こったこと

Basic認証のついたURLを必要としており、かつ必要に応じてこのURLを表示したい。ただ、表示するときにBasic認証がそのままついた状態だと困る。そのため、Basic認証のついたURLから認証情報だけを外したい。

- https://username:password@testtest.com
+ https://testtest.com

コードはこう

const removeBasicAuth = (urlWithBasicAuth) => {
  const url = new URL(urlWithBasicAuth);
  url.username = "";
  url.password = "";
  return url.toString();
};

const targetUrl = "https://username:password@testtest.com";
const url = removeBasicAuth(targetUrl);
console.log(url); // "https://testtest.com"

フロントエンドではE2Eテストだけでも書くようにした

起こったこと

現在運用中のフロントエンドだけで動いているWebアプリケーションについて、テストコードが全く書かれていない状態だったので、ユニットテストなどをいろいろすっ飛ばしてE2Eテストだけでも書くようにした。

やったこと

とにかく既存機能のE2Eテストを書く

今の動いている通常の機能だけでもE2Eテストを書いた。これから出来る新機能やバグ修正パッチが完成する前に作り終えないと、これから発生するエンバグの時期がわからなくなる。E2Eを作成中に出来上がった新機能についてはいったん考えない。とにかく既存機能にテストを書く。

既知のバグを再現する手順をテストを書く

かつて発生したバグが出た操作をE2Eに記載する。既知のバグで修正済みのはずなので、実行すればパスするはず。だよね?

ユーザーの動きに近い再現方法を書くのが良いのか、それとも機械的に最短で再現できる方法を書くのが良いか、いつも迷う。

新機能や新バグを見つけたときは都度E2Eに追加していく

上の2つが出来たら開発チームに横連携して、レビュー、マージする。チームには新機能を開発する、あるいはバグが発生したときは都度E2Eを書くようお願いする。

あきらめたこと

PlayWrightでいろんなブラウザで起動すること

PlayWrightには3つぐらいブラウザが同時に実行されるけど重いからChromeだけでも動かすようにした。これ本当にCIで実行できるのだろうか。

E2Eだけでテストを網羅すること

受け入れテストを完全にE2Eで自動化に出来そうだと思ったけど、やっぱり人によるの検証は別途必要そう。モンキーテストのような、そういうテストは人間がやらないとだめだ。特に文章がおかしいとか、文字がはみ出ているといったテストは人間がやらないと見つからなさそう。書いていること以外のことはできないのがE2Eなんだと思った。

頑張りすぎること

もう少し頑張ったらきれいで汎用性の高いものがかけそうだったものがあるのだが、まずは終わらせることを目標とした。そうじゃないと延々とテストコードを書き続けることになりそう。終わりがないのが終わり。

テストコードがあると安心

つぎはぎ感があるがテストコードがかけた。これがあると新機能を作るときにもエンバグの怖さがだいぶ減る。書いてよかった。いま、テストコードが足りていないアプリについてはテストコードを書くようにしよう。

WindowsでもReactNativeが動いた(ReactNative for Windows + macOS)

起こったこと

Win用アプリを作ろうと思っていろいろと調べていたらReactNative for Windows + macOSというものを見つけた。

microsoft.github.io

始めるために色々必要な手順はこちら

microsoft.github.io

軽く作ったもの

時間が表示されるようなアプリ。これからいろいろいじってみたい。

GA4の「タグ付けの詳細設定」と「内部トラフィックの定義」の場所

日付

2022/11/07

起こったこと

GA4を導入したけど、自分のアクセスも普通に拾っているので制限をかけたい

検索をかけるとGA4の設定=>データストリーム=>自分のGA4タグ名=>タグ付けの詳細設定=>内部トラフィックの定義=>作成=>...

となっているが「タグ付けの詳細設定」と「内部トラフィックの定義」が見つからない

名称の変更

この手のサービスにはよくあることで、名称が変更となっていたようだ。

2022/11/07現在では

GA4の設定=>データストリーム=>自分のGA4タグ名=>タグ設定を行う=>すべて表示=>内部トラフィックの定義=>作成=>...

でよいみたい。

Node.jsで複数のJSONファイルを1つにまとめたい

バージョン情報

$ node -v
v16.15.1

起こったこと

特定のディレクトリ内にある複数のJSONファイルをを1つにしたいという要望が出た。

JSONファイルの名前をKeyにして、中身をvalueとしてを持つような単純なものである。

hogehoge.json

{
  "name": "aiueo"
}

piyopiyo.json

{
  "weight": 60
}

まとめた後のjson

{
  "hogehoge": {
    "name": "aiueo"
  },
  "piyopiyo": {
    "weight": 60
  }
}

つくったもの

大した理由ではないがTypeScriptではなくNode.jsで書くことにした。

// merge_json.js
const path = require("path");
const fs = require("fs");

const printUsage = () => {
  console.log("Usage: node merge_json.js <path_to_jsons_dir>");
  process.exit(1);
};

if (process.argv.length < 3) {
  printUsage();
}

const dir = process.argv[2];
const target = path.resolve(process.cwd(), dir);
const mergedJson = {};

const removeExtension = (filename) => {
  return filename.replace(/\.json/, "");
};

fs.readdirSync(target).forEach(fileName => {
  if (!/\.json$/.test(fileName)) return;
  const json = fs.readFileSync(path.resolve(target, fileName), { encoding: "utf-8" });
  const key = removeExtension(fileName);
  mergedJson[key] = JSON.parse(json);
});

fs.writeFileSync(process.cwd() + "/merged.json", JSON.stringify(mergedJson, null, 2), { encoding: "utf-8" });

ターミナルからnode merge_json DIR_PATHと入力すればマージされたJSONmerged.jsonという名前で出力される。