OmniAICreator/Qiita-1.07M huggingface dataset:
How to identify Service Mesh V2 managed resources in OpenShift

#### OpenShift Service Mesh
OpenShift Service Mesh は、マイクロサービスベースのアプリケーションを接続、管理、監視する方法を統一し、Service Mesh 内でネットワーク化されたマイクロサービスの動作を分析および制御することができます。

OpenShift Service Mesh は、オープンソースの Istio プロジェクトをベースに、Kiali (Istio コンソール) や Jaeger (分散トレース) といった他のオープンソースプロジェクトを取り込むことで機能を追加したものですが、Service Mesh を導入・構成すると、Service Mesh Operator によって、Network Policy, ConfigMap 等の様々なリソースが自動的に作成されます。

#### How to identify Service Mesh V2 managed resources
このような Service Mesh Operator の実装は、しばしば、ユーザーが独自に作成した Network Policy, ConfigMap 等のリソースとの区別を困難にすることがありますが、どのリソースが Service Mesh Operator によって作成されたのか、Annotation を利用して区別することが可能です。

https://docs.openshift.com/container-platform/4.11/service_mesh/v2x/upgrading-ossm.html#ossm-upgrade-considerations_ossm-upgrade
>The maistra.io/ label or annotation should not be used on a user-created custom resource, because it indicates that the resource was generated by and should be managed by the Red Hat OpenShift Service Mesh Operator.

>Before upgrading check for user-created custom resources that include the following labels or annotations:
>
> - maistra.io/ AND the app.kubernetes.io/managed-by label set to maistra-istio-operator (Red Hat OpenShift Service Mesh)
> - kiali.io/ (Kiali)
> - jaegertracing.io/ (Red Hat OpenShift distributed tracing platform)
> - logging.openshift.io/ (Red Hat Elasticsearch)
>
>Before upgrading, check your user-created custom resources for labels or annotations that indicate they are Operator managed. Remove the label or annotation from custom resources that you do not want to be managed by the Operator.

以下の例では、Network Policy の確認に際して、`app.kubernetes.io/managed-by` を `ANNOTATION` フィールドとして取得しています。
```shell
$ oc project -q 
my-project
$ oc get networkpolicy -o custom-columns='NAMESPACE:.metadata.namespace,NAME:metadata.name,ANNOTATION:.metadata.labels.app\.kubernetes\.io/managed-by'
NAMESPACE        NAME                             ANNOTATION
my-project       my-network-policy-allow          <none>
my-project       my-network-policy-deny-all       <none>
my-project       istio-expose-route-smcd-mysdc-1  maistra-istio-operator
my-project       istio-mesh-smcd-mysdc-1          maistra-istio-operator
```
`ANNOTATION` に `maistra-istio-operator` が設定されているリソースが、Service Mesh Operator によって自動的に作成されたものであることが分かります。

Kiali, Jaeger (Red Hat OpenShift distributed tracing platform), Elasticsearch についても同様に、それぞれの Annotation を確認することが出来ます。
M1 MacでビルドしたDocker Imageが実行エラーとなる場合の対処

## 問題
Amazon ECRに格納したDocker imageをcronジョブで実行しようとしたところ以下のエラーが出た。

```bash
/usr/local/bin/python: exec format error
```

## 結論
docker imageをbuildする際にplatform指定が必要だった。

```bash
$docker build --platform linux/amd64 -t build対象 .
```
puppeteer (node.js) – BASIC認証 + テキスト入力 + ボタンクリック + スクリーンショット撮影 のスクリプト例

```js
// package.json
//
// {
//   "dependencies": {
//     "puppeteer": "^21.1.1"
//   },
//   "type": "module"
// }

// $ node example.js

import puppeteer from 'puppeteer'

async function sleep(delay) {
  return new Promise((resolve) => setTimeout(resolve, delay))
}

(async () => {
  const browser = await puppeteer.launch({headless: false})
  const page = await browser.newPage()

  const url = 'https://example.com'

  //Basic認証のAuthorizationヘッダーを設定
  const BASIC_AUTH_USERNAME = 'username'
  const BASIC_AUTH_PASSWORD = 'password'
  await page.setExtraHTTPHeaders({
    Authorization: `Basic ${new Buffer(`${BASIC_AUTH_USERNAME}:${BASIC_AUTH_PASSWORD}`).toString('base64')}`,
  })

  const response = await page.goto(url, { waitUntil: ['domcontentloaded'], timeout: 60000 })

  if (response) {
    const status = response.status()
    const statusText = response.statusText()

    console.log(status)
    console.log(statusText)

    await sleep(1000)

    await page.type("[id='email']", 'example@example.com')
    await page.type("[id='password']", '************')

    await sleep(1000)

    await page.screenshot({path: './step1.png'})

    await page.click("[id='submit']")

    await sleep(1000)

    await page.screenshot({path: './step2.png'})

  }

  await browser.close()
})()
```

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
Apache2のログの設定

## 環境
Apahce2.4
Ubuntu20.4

## ログの設定
Apache2には、デフォルトで下記の２つログが作成されます。

```/var/log/apache2
error.log
access.log
```

ログの名前と出力先のパスは、つぎのコンフィグファイルの中で設定されています。000-default.confを有効にしていない場合（sites-enabledにリンクを作っていない場合）は、自作したコンフィグファイルに、ログを出力する記述を追加しておく必要があります。

```/etc/apache2/000-default.conf
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
```

APACHE_LOG_DIRの環境変数は、つぎの個所で設定されています。パスの末尾に$SUFFIXという変数がついています。設定ファイルの上の方を見ると、１つのOSの中でApach2を２個動作させている場合に、２個目のパスがSUFFIXにセットされるようになっています。
```/etc/apache2/envvars
export APACHE_LOG_DIR=/var/log/apache2$SUFFIX
```

出力されるログは、際限なく肥大化されるようにはなっていません。デフォルトでログローテーションが行われるように設定されています。Apacheからログローテーションを行うデーモンが個別に提供されているわけではなく、Ubuntuに標準で付いている、logroteツールを使って行うようになっています。

Apacheがログローテーションを行う設定ファイルは、インストール時に下記に作成されます。logroteファイルの中で、logrote.dフォルダ内に作成された設定ファイルをIncludeするように設定されてています。
```
/etc/logrote.d/apache2
```
VuexでのMutationとActionの命名規則について

## はじめに
VuexのMutationとActionには一般的な命名規則がありますが、これは必ずしも固定されたものではありません。この記事では、なぜ多くの開発者が特定の命名規則を採用するのか、その背景にある理由を解説します。

Mutationの命名規則
一般的に、VuexのMutationは全て大文字で命名されることが多いです。以下のような感じです。

~~~
const mutations = {
  SET_ITEM(state, item) {
    state.item = item;
  },
  REMOVE_ITEM(state) {
    state.item = null;
  }
};
~~~

## 大文字を採用する理由
可読性: 全て大文字で書かれた文字列は目立ちやすく、コード内で状態が変更される場所をすぐに識別できます。

１、一貫性: 一貫した命名規則を使用することで、コードベースが整理され、メンテナンスやデバッグが容易になります。

２、慣例: Redux（Reactの状態管理ライブラリで、Fluxアーキテクチャの一種）でも、このような命名規則が推奨されています。Vue.js コミュニティでもこの慣習が多く見られます。

## Actionの命名規則
一方で、Actionの命名は通常 camelCase や kebab-case が使われます。

~~~
const actions = {
  setItem({ commit }, item) {
    commit('SET_ITEM', item);
  },
  removeItem({ commit }) {
    commit('REMOVE_ITEM');
  }
};
~~~

## なぜcamelCaseやkebab-caseが使われるのか
１、可読性: Action名はより「説明的」であり、何を行っているのかが明確であるべきです。

２、複雑性: Actionは多くの場合、非同期処理や複数のmutationを含むなど、より「複雑な」操作を行う可能性があります。

## まとめ
命名規則はプロジェクトやチームによって異なる場合がありますが、どの命名規則を採用するにせよ、プロジェクト全体で一貫性を持たせることが重要です。
Googleスプレッドシートの印刷時、未選択のプルダウンのグレーを印刷したくない

### やりたいこと ###
・Googleスプレッドシートでプルダウンの背景色を印刷したくない。


　Googleスプレッドシートでプルダウンを作成すると、角丸長方形のグレーが表示されます。
リストで選択したときに、背景色を白にすることで、色がついていないようにできますが、未選択時のままだと角丸長方形のグレーが印刷されてしまいます。
![スクリーンショット 2023-09-05 113320.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132630/cc5892e9-faf9-2a58-48da-0ccdd12e4658.png)


それを印刷しない方法が分かりません。教えてください。
Azure Web App for Containers に VOICEVOX コンテナをデプロイする

この記事では、最近？流行りの [VOICEVOX](https://github.com/VOICEVOX/voicevox_engine) を Azure Web App for Containers にデプロイする方法を共有します。VOICEVOX の利用規約などは別途 [VOICEVOX のレポジトリ](https://github.com/VOICEVOX/voicevox_engine)で確認してください。

## Azure Web App for Containers

Azure Web App は Windows/Linux ベースの環境に .NET を始め、多くの言語をサポートする Web アプリのホスティングサービスですが、Docker コンテナをデプロイすることもできます。

https://learn.microsoft.com/ja-jp/azure/app-service/scripts/cli-linux-docker-aspnetcore

今回はここに VOICEVOX のコンテナをデプロイします。

ポイントは以下の通り。
- コンテナは通常の手順でデプロイできる
- イメージは voicevox/voicevox_engine:cpu-ubuntu20.04-latest を利用
- WEBSITE_PORTS を使ってポートを 443 から 50021 にリダイレクト

## 手順

1. Linux ベースで Docker Container 用の Web App を作成する。SKU は Free で動作可能。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/7e34c4b5-27f4-4642-5d52-fad9de5541ba.png)
1. 以下のコマンドで VOICEVOX をデプロイする。
    ```shell
    az webapp config container set -c voicevox/voicevox_engine:cpu-ubuntu20.04-latest --name 
    <Web App の名前> -g <リソースグループ名>
    ```
1. デプロイが完了したら Web App の Configuration より新しい Application settings を追加。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/46cdbfa3-b9b8-cd6d-500e-65675550204d.png)
1. 名前: WEBSITES_PORT 値: 50021 を追加。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/0a0265ee-e7d5-65ef-b201-820733348387.png)
1. 保存して再起動。

## テスト

デプロイが終われば HTTPS/443 よりアクセスが可能です。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/534163f3-87cb-d4f6-b4fa-f31f49ef0b3a.png)

## まとめ

Azure は Docker コンテナをホストできるサービスが複数存在しますが、手軽に利用できる選択肢として Web App も是非検討してみてください。
quiverを微調整する小技 (Matplotlib + Cartopy)

matplotlib + cartopyで地図上にベクトルを描く時，特に複数の図で同じscaleでベクトルを描きたい際に，quiver関数のscale値やwidth値の調節が面倒くさくて気が滅入ってしまうので，その小技を日本語にしておく．

2023/09/27追記
scale値に加えwidth値も同様に_init()により取得可能．

2023/12/08追記
cartopyで地図上にプロットする際は`regrid_shape`を先に設定すると吉（ベクトルの描画間隔が変わり、scale値も変わるので）

参考リンク
[how to use matplotlib quiver scale - Stack Overflow](https://stackoverflow.com/questions/34025306/how-to-use-matplotlib-quiver-scale)

```python3
q = ax.quiver(x, y, u, v)  # scale=None, width=Noneがデフォルトで設定される

print(q.scale)
# None  # 描画されるquiverのscale値を入手できない

q._init()  # これが大事っぽい

print(q.scale)
# 1.1610226806616049  # scale値を取得！

print(q.width)
# 0.0024  # width値を取得！
```

`ax`はMatplotlibの[axisインスタンス](https://matplotlib.org/stable/tutorials/introductory/quick_start.html#sphx-glr-tutorials-introductory-quick-start-py)．`quiver`はベクトル描画のメソッド（詳細は[本家](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.quiver.html)や[こちら](https://yyousuke.github.io/matplotlib/cartopy.html)を参考にしてほしい）．


肝心なのは，普通に`q.scale`をすると`None`（或いは与えた引数scaleの値）が返るが，`_init()`をすることによってmatplotlib内で”よろしく”設定してくれたscaleを取得できること．

上記の例では，`quit()`して作図前にscaleを確かめ（`1.1610226806616049`），その値を参考に`scale`や`width`引数を設定し，改めて描画する．width値も同様．

```python3
q = ax.quiver(x, y, u, v, scale=1.16, width=0.003)
```

あとは図を見ながら`scale`や`width`の値を微調整すれば良い（scale値を大きくすれば矢印は短くなり，width値を大きくすれば矢印は太くなる）．

（length,headlength,headwidth,etc...の詳細設定は[本家を参照](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.quiver.html)．width値を基準に相対的に設定されるらしい）

（なお、transform=ccrs.PlateCarree()は省略してるので注意）
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. エラーが出る問題を解決する

# 状況
`docker-compose.yml`があるディレクトリで

``` zsh
$ docker compose up -d
```
を実行したが、以下のようなエラーが出る。

``` zsh
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
```

# 原因
Dockerデーモンが起動されていない。
> Dockerデーモンとは、コンテナを管理するために常駐するプロセスのこと。

# 解決策
Docker Desktop（GUIアプリケーション）を起動させるとうまくいった。
OpenCVのCMake中にCould NOT find CUDNNが出た時の対処法

## エラー

`--Could NOT find CUDNN (missing: CUDNN_LIBRARY CUDNN_INCLUDE_DIR) (Required is at least version “7.5”)`

## 環境
Windows Server 2022上のWSL2のUbuntu 20.04
CUDNNはインストールしている（のに出る）

## 対処法
1. ビルドディレクトリの中に自動生成されているはずの`CMakeCache.txt`を開く
2. オプションのひとつの `CUDNN_LIBRARY` を探して、cudnnのディレクトリを指定する
  デフォルトだと `/usr/local/cuda` にインストールされるようなので自分はこういう風に修正した


```
CUDNN_LIBRARY=/usr/local/cuda-11.8/lib64
```
fakexrandr を使ってみる

4k ディスプレイを使っているけれども、リモートでプレゼンをしたりしているとサブディスプレイが欲しくなる。更にテレカンファレンスシステムの画面を確認したり、同時配信の状況も確認したりしているとトリプルディスプレイやクアッドディスプレイにしたくなる。

今回は 4k ディスプレイを分割して、マルチディスプレイの使いごごちに近づけてみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/1be46f47-2b49-6ef5-2baa-7101c3c8f044.png)

# 環境

Ubuntu 22.04 LTS


# インストール

事前に必要なパッケージをインストール
```
$ sudo apt-get install xorg-dev libglu1-mesa-dev build-essential \
 python3-gi python-gi-dev python-gi-cairo
```

ダウンロード
```
$ git clone https://github.com/phillipberndt/fakexrandr.git
$ cd fakexrandr
```

インストール
```
$ make
$ sudo make install
```

実行・設定

```
$ fakexrandr-manage

```

以下のように設定した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/1be46f47-2b49-6ef5-2baa-7101c3c8f044.png)

1〜7 は 元々は 1枚の8kディスプレイ。8 は Full-HDディスプレイ。



# アンインストール

インストールしたあと、物理ディスプレイのレイアウト変更設定がどうもうまくいかない。

また、 xrandr を実行すると、
```
fakexrandr/mmap(): Invalid argument
```
と出てくるので設定の変更を行うときには fakexrandr をアンインストールするのが良さそうだ。

以下のようにすると

```
$ sudo make uninstall
```
以下のように表示がなされるが、この表示通り動作しているようだ。
```
TARGET_DIR=`sed -nre 's/#define FAKEXRANDR_INSTALL_DIR "([^"]+)"/\1/p' config.h`; \
[ -d $TARGET_DIR ] || exit 1; \
strings $TARGET_DIR/libXrandr.so | grep -q _is_fake_xrandr || exit 1; \
rm -f $TARGET_DIR/libXrandr.so $TARGET_DIR/libXrandr.so.2 $TARGET_DIR/libXinerama.so.1 /usr/bin/fakexrandr-manage; \
ldconfig
```
Gitコマンドへのエイリアス設定

新規PCに対して再設定をしていくので、設定方法をメモ。

### Gitコマンドに対するエイリアス設定

gitをgにする。

```zsh
% vi ~/.zshrc
```

下記を追加する。

```.zshrc
alias g='git'
```

```.zshrc
% source ~/.zshrc
```

確認

```.zshrc
% g --version
git version 2.39.2 (Apple Git-143)
```

### Gitコマンドのオプションへの設定

pullをpにする。

```zsh
% git config --global --list
fatal: unable to read config file '/Users/${User name}/.gitconfig': No such file or directory
```

```zsh
% git config --global alias.p pull
```

確認

```zsh
% git config --global --list
alias.p=pull
```

```zsh
% g p
remote: Enumerating objects: 37, done.
remote: Counting objects: 100% (37/37), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 37 (delta 28), reused 37 (delta 28), pack-reused 0
Unpacking objects: 100% (37/37), 9.70 KiB | 220.00 KiB/s, done.

〜 省略 〜
```

## その他

前職のGitコマンドのエイリアス設定をエクスポートするの忘れてた…。
なにか便利なエイリアス設定があったらコメントで教えていただけると嬉しいです😅
「良いコード・悪いコードで学ぶ設計入門」を読んで思ったこと

# はじめに

わたしは社会人3年目のひよこエンジニアです。皆さんに撮って良いコードとは何ですか？わたしはコードを見たときにクラス、関数、変数がどのような役割を期待されているのかどうかが名前から把握できることです。しかし、良いコードの条件はそれだけではないということを後述の書籍から知りました。  
今回は[良いコード／悪いコードで学ぶ設計入門 保守しやすい 成長し続けるコードの書き方](https://gihyo.jp/book/2022/978-4-297-12783-1)を参考に、今後のコーディングにさらに磨きをかけていきたいと思っています。  

# 前提

本記事では上記書籍を読んでみた感想等を実際の業務にあっている内容のみ記載していきたいと思っています。そのため、書籍の要約かと思いきや、私自身に役に立つ内容ですので、ご了承ください。  

# 全体的な感想

個人的に衝撃的だったのは、良いコードって名前の命名だけに気を付けていれば良いだけではないのか。。。という事でした。本書で述べている良いコードには、もちろん名前の命名もそうですが、そのほかのロジック的な観点も記載がありました。確かに言われてみれば、「確かにそうだ」と納得しました。  

# 良いコード／悪いコードで学ぶ設計入門 保守しやすい 成長し続けるコードの書き方

## 自己防衛責務

クラスや関数にはそれ単体で動作するように設計することが推奨されます。なぜなら、仮に引数として不正値(想定しない値)が渡された場合エラーとなるからです。たとえば、消費税の計算をする関数に「-100」が渡されると計算がうまくされずエラーになってしまいます。  
そのような問題を解消するために関数の最初に不正値を検知したら例外をスローするという処理を実装します。  

```JavaScript
Money (amount) {
    if (amount < 0) {
        throw new IllegalArgumentException ('金額には0以上を指定してください。');
    }
・
・
・
}
```

## イミュータブル

値はイミュータブル(不変)にして再代入を避けるということが推奨されます。なぜなら、途中で変数に値が再代入されると予期せぬエラーが怒ってしまう可能性があるからです。たとえば、引数として渡された値は正常値なのに途中で不正値が再代入されることでエラーが発生してしまいます。  
そのような問題を解消するために新しい変数を宣言する際には定数を宣言するようにします。  

```JavaScript
const amount = 100;
```

## DRY原則

DRY(Don't Repeat Yourself)と呼ばれる原則のことです。つまり、コードの重複を許すなという原則です。しかし、この原則は単にコードの重複を許すなという事ではなく、同一の概念から生まれるコードは重複を許さないという意味です。つまり、概念が違えばコードは重複してもよいという考え方になります。  
概念が違う同一コード、もしくは似たようなコードだからとすべて重複をなくすと蜜結合となってしまいます。  

## 技術以外の要因

わたしは個人的に技術以外の要因は大いにあると思っています。もちろん、天才集団の集まりであれば技術的に解決する方が早いでしょう。しかし、私を含め世の中の多くの人は天才ではないと思います。そもそも天才は母数が少ないから「天才」というラベリングがされるのです。そのため、そんな天才ではない平凡な技術者はどのような要因によりどのような問題が生じるのでしょうか。

### コミュニケーション不足

同じ開発のメンバーで同じアプリケーションの実装をしていると仮定します。ソースをリリースし、テストを実施するとエラーばかり。生産性を上げるどころの話ではありません。むしろ、生産性が下がってしまいます。  
本書ではこのような問題の原因はメンバー同士のコミュニケーションが希薄だからだと解説しています。確かに、メンバー同士のコミュニケーションが希薄だとメンバーが何を開発して、どのようなロジックで、どのような記述をしているかわかりません。それらを解決するためにコミュニケーションが必要だと認識しました。

### 心理的安全性

チームメンバーとコミュニケーションをとる(関係の改善)には、心理的安全性の向上が不可欠です。本書では、心理的安全性とは「自分が発現することを恥じたり、拒絶されるなど、不利益を被ることがないことをチームで共有されている心理状態」や「安心して自由に発言したり、行動できる状態」と記載されていました。つまり、安心できる環境ということですね。  
したがって、心理的安全性を向上させることによって、自然とコミュニケーションが増え、チームメンバーとの関係が改善され、最終的にはエラーの数が少なくなるという結論に至ります。  

# さいごに

以上、書籍から印象が強く残っている内容を記載いたしました。内容が濃いため、全て紹介することはできませんが、ご容赦ください。
基本情報技術者試験受かるためにやったこと

# 面倒だからこれ見ろって言うために書きます

## A(午前)免除試験

### ひたすら過去問道場やる
本当にこれしかない
とにかく覚えるしかない
例えば「スプーリングはスループットを向上させる」などはたしか平成26年春から令和1年までに4~5問出てたりする。
こうした共通点を見つけて覚えるのもいい。
ただ本当に人それぞれだからあまり言うことはない。

## 勉強の範囲
自分は令和1年度~26年度春までの1000問弱をひたすらやった。
それ以前のものはほぼやっていない。
これは今でも正解だと思っている。
Aは**問題の形式を覚えるより、知識をつけるほうが大事だと思う**
今までやってきた問題と形式は違うが言ってることは超簡単みたいなことは多い。
自分が受けたA免除は直近2年の免除試験からの問題も出たので免除試験も一回やっておくといいかも。

### 大体どこから問題を持ってきているか
FEの過去問やってればわかるものが40前後、うち20問弱はほぼそのまま出た。
AP(応用情報)から10問弱、SGから数問、よくわからん出典から2~3問、完全オリジナル問題が1問
APの問題は用語がわからないと絶対にわからないものとかも出る(自分はUPSがわからなかった)
そういう問題は捨てざるを得ない。
ただ50/60問くらいはちゃんと過去問やって考えればわかる問題なので諦めずに考えて~~雰囲気で~~答えよう。

## B(午後)試験

### 形を覚える
これも数をこなすと言える。
**同じ問題を何度もやるより、たくさんの問題をやるほうがいい**
1度問題の意味が分かったらもうやらなくてもいいと思う、前日に見返すくらいで。
Bは自分で考える力もAより必要になるのでただ答え覚えても何の意味もない。
ここで形を覚えるとは問題、コード(疑似言語)、回答群を見て大体**どんな問題かを見定めるようになることを指す**
まずパッと回答群を見る、ここで
* コードの穴埋めなのか
* コードをトレースして答えるのか
* ほぼ数学の問題なのか

がわかる。
次に問題を見て大体なにを言いたいのか掴む。
最後にコードを見てトレースしたり、構造を考えたりする。
ここはよく前後する。
5割の問題は問題文見ただけではわからないので問題文とコードは一緒に見ることになる。
**この問題の意図を読み取る時間が一番大変なのでここを短縮するためにいろいろな問題に手を出さないといけない**

問題は~~素人目で見て~~洗練されていて必要のない情報はあまりないし、なんでこここんな書き方してるの?みたいなことは少ない。
**ただし、リスト番号は絶対に1から始まる**
自分はこの時pythonを触り始めてたので問題を見てかなり困惑した。

### プログラミング用語や英単語を覚える
例えばstr(string 文字列型),int(integer 整数型),list,
単方向リストのcurr(current 現在の),prev(previous 前の)がわからないとそもそも問題が解けないといったことが起きる
英単語といっても別に難しいものではなくて、numerator(分子),denominator(分母)など覚えるものの数は少ない
numerator,denominaterがわかっていれば問題が一気に解けやすくなることがあったのでぜひ覚えておきたい

### 参考書など
IPAの出しているサンプル問題と[かんたん合格 基本情報技術者予想問題集 令和5年度](https://www.amazon.co.jp/%E5%85%A8%E6%96%87%E9%9B%BB%E5%AD%90%E7%89%88%E4%BB%98-%E3%81%8B%E3%82%93%E3%81%9F%E3%82%93%E5%90%88%E6%A0%BC-%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85%E4%BA%88%E6%83%B3%E5%95%8F%E9%A1%8C%E9%9B%86-%E4%BB%A4%E5%92%8C5%E5%B9%B4%E5%BA%A6/dp/4295015741)(B問題だけ)を2周した。
**一番大きかったのはpythonを触っていたこと**だった。
pythonは疑似言語と形がよく似ているので一度やってみるべきだと思う。
特にatcoderはよかった。
atcoderのA問題ができるようになるだけでかなり力になる。

### セキュリティ
特にいうことはない。
Aのセキュリティと使う知識はほぼ同じなので問題形式さえ覚えればいい。
「見つかった脆弱性」の欄と回答群だけで答えられる問題もあるくらい簡単なのでここで点を稼ぎたい。

<details>
<summary>自分語り</summary>
<div>

専門学校入って4月からとりあえず基本情報目指すか、という感じで初めて6月の免除試験に受かった。
最終的に過去問道場900問やって9割取れるまでになった。
本番は50/60点だった。
Bは6月終わりから7月終わりまで勉強して735/1000点だった。

～～～展開ここまで～～～
</div>
</details>

## まとめ
Aはひたすら問題をやって知識つけろ、問題見ただけで答えわかるようになれば受かる
Bはいろんな問題やって形覚えろ
LXDでubuntu, AlmaLinuxを構築した場合の初期設定

## Ubuntu
### TL;DL
```bash
passwd root
```
```bash
timedatectl set-timezone Asia/Tokyo
hostnamectl set-hostname ubuntu-server
apt -y update
apt -y install openssh-server
echo "PermitRootLogin  yes" | tee /etc/ssh/sshd_config
echo -e "password\npassword\n" | passwd root
systemctl start ssh && systemctl enable ssh
```


### rootパスワードの設定
```bash
$ passwd root
```

### タイムゾーン、ホストネームの設定
```bash
timedatectl set-timezone Asia/Tokyo
hostnamectl set-hostname ubuntu-server
```

### sshの設定
```bash
apt -y update
apt -y install openssh-server
echo "PermitRootLogin  yes" | tee /etc/ssh/sshd_config
echo -e "password\npassword\n" | passwd root
systemctl enable sshd && systemctl restart sshd && systemctl start sshd
```
DatabaseTransactions と RefreshDatabaseの違いと使い方


Laravelフレームワークでは、テストの手助けをするためにいくつかの便利な機能が提供されています。その中でも、特にデータベースとのやり取りをテストする場面でよく使われるのが `DatabaseTransactions` と `RefreshDatabase` トレイトです。

これらのトレイトの目的と使い方、そして違いについて解説します。

## RefreshDatabase

`RefreshDatabase` トレイトは、テストケースが実行される前にデータベースをマイグレーションし直します。つまり、テストケースごとに全てのテーブルが初期状態に戻ります。

```php
use Illuminate\\Foundation\\Testing\\RefreshDatabase;

class ExampleTest extends TestCase
{
    use RefreshDatabase;

		public function setUp()
    {
        parent::setUp();
    }

    public function testDatabase1()
    {
        // データベース操作のテストコード
    }

		public function testDatabase2()
    {
        // データベース操作のテストコード
    }
}

```
### 動作フロー
```mermaid
flowchart TB
    id1(["migrate & seeder"])-->
    id2(["setUp()"])-->
    id3([testDatabase1])-->
    id4([testDatabase2])-->
    id5([マイグレーションがロールバック])
```

### 利点と制限

- **状態**: 各テストでデータベースがリセットされるため、状態の管理が非常に容易。
- **速度**: マイグレーションとシーディングが必要な場合は、`DatabaseTransactions`よりも遅くなる可能性がある。

## DatabaseTransactions

`DatabaseTransactions` トレイトを使用すると、テストケース内で行われるデータベースの操作はトランザクション内で行われます。このトランザクションはテストケースの実行が終了するとロールバックされます。

```php
use Illuminate\\Foundation\\Testing\\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use DatabaseTransactions;

		public function setUp()
    {
        parent::setUp();
    }

    public function testDatabase1()
    {
        // データベース操作のテストコード
    }

		public function testDatabase2()
    {
        // データベース操作のテストコード
    }
}

```

### 動作フロー
```mermaid
flowchart TB
    id1(["migrate & seeder"])-->
    id2(["setUp()"])-->
    id3([testDatabase1])-->
    id4([testDatabase2])-->
    id5([データベーストランザクションがロールバック])
```

### 利点と制限

- **速度**: トランザクションは比較的高速であり、テーブルを再構築する必要がない。
- **状態**: 各テストが独立してトランザクション内で動作するため、テストの間に状態が漏れ出る心配が少ない。

## どちらを使うべきか？

`RefreshDatabase`

- データベースのスキーマ自体をテストしたい場合
- 一時テーブル(Temporary Table)を使う場合

`DatabaseTransactions` 

- 大量のテーブルが存在する場合
SOP8ソケット

SOP8のソケットは高価でスペースをとるので、こんな風にしてDIPのソケットで代用しています。

![写真（2023-09-05 8.50）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/048a135d-996b-2437-86a4-bfaad7edc8b2.jpeg)

隣にあったSDRAMの上に板ばねのICソケットをピンを折って、エポキシボンドで接着して、ワイヤーリングしています。

SOPのパターンは弱いので、ICソケットのピンからハンダ付けするのがコツです。

変換基板の足は秋月電子の「基板用リードフレーム」を使っています。ハンダ付けは両方乗っけて洗濯ばさみなどではさんで立ててするのがいいです。

SOP8を剥がすときは低温ハンダを使い、二丁ハンダごてでやりました。

flashromで焼いては試してを繰り返します。
Public Sector Org



# エラー

+ [Public Sector Org error](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007GIFDh)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/cfeb2261-84ee-dae0-1ee6-92569d0cb3cd.png)
インライン編集

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)




# インライン編集を無効化する

+ [How to disable inline editing?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007FUnpY)

以下の２つの設定でインライン編集は可能になる。

There are many permission which you can turned off for your user to enable the inline editing for your users.

+ Enable Inline Editing' and 'Enable Enhanced Lists' preferences is required. (under Setup | Customize | User Interface).
+ The 'Mass Edit from Lists' permission(  Your profile name>Edit> Under  General User Permissions>Mass Edit From List ) 

+ [How to disable inline edit in list view in lightning ?](https://developer.salesforce.com/forums/?id=9060G0000005jfKQAQ)

+ uncheck the “Mass Edit from Lists” permission for the users that you want to prevent editing in list views.
+ Setup > Customize > User Interface > Enable Enhanced Lists and uncheck that box.

+ [Can I disable inline editing for list views only?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A7OCYSA3)

しかし、機能しなかったようです。

よって、奥の手。レコードタイプを設定して強制的にインライン編集を止めます。

 One quick work-around is, to add a default record type. 

 If you add record type then you need to filter the list by record type for inline edit. If you don't filter the list view with record type, then you automatically Salesforce disables the list view inline edit. 


https://salesforce.stackexchange.com/questions/312341/disable-inline-editing-for-fields-in-the-list-view-in-lightning

# 機能しない？

+ [Missing Checkbox Column : Inline Edit is disabled](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007HNcA9)
JavaのMapと使いどころ

## Mapとは

「キー」と「値」をペアにして複数の値を格納できるもの

## Mapの種類
 Mapはインタフェースなので実装クラスを用意して使う必要がある。
実装クラスにはHashMap,LinkedHashMap,TreeMapなどがある。

## Mapのメソッド

1.putメソッド　Mapにデータを追加

2.getメソッド　Mapからデータを取得

3.keySetメソッド　Mapのすべてのキーを出力

## こんな時に使える

・大量の何かをキーと紐づけて回すとき。

ex.aからzまでの26文字を追加する

```
Map<Character,Integer> atozMap = new HashMap<>() {
        	{
        	
        		for(char c = 'a';c < 'z'+1;c++) {
        			put(c,0);
        		}
        	}
        };
```
電子工作メモ - シリアル通信(UART)

# シリアル通信(UART)

- TX: 送信
- RX: 受信
- baudrate: 通信速度。両側で合わせる。

## USBに統合されているシリアル

```python
import time

print("Raspberry Pi Pico initialization completed !")

while True:
    print("Running time : ", time.time()%60,"s")
    time.sleep(1)
```

```python
print(str("\nRaspberry Pi Pico initialization completed!\n")
      + str("Please input some characters,\n")
      + str("select \"Newline\" below and click send button. \n"))
while True:
    print("inputString: ",input())
```

## UART

- UART0, UART1 の２つ使える

|type|GPIO|Pin|
|:--|:--:|:--:|
|UART0 TX|GPIO0| 1|
|UART0 RX|GPIO1| 2|
|UART1 TX|GPIO8|11|
|UART1 RX|GPIO9|12|

- TX と RX をつなぐ
  - UART0 TX(GPIO0) <=> UART1 RX(GPIO9)
  - UART0 RX(GPIO1) <=> UART1 TX(GPIO8)

    ```python
    from machine import UART, Pin
    import time
    
    myUsart0 = UART(0, baudrate=9600, bits=8, tx=Pin(0), rx=Pin(1), timeout=10)
    myUsart1 = UART(1, baudrate=9600, bits=8, tx=Pin(8), rx=Pin(9), timeout=10)
    
    while True:
        rxData = bytes()
        input_cnt = str(input("myUsart1: "))
        myUsart1.write(input_cnt)
        time.sleep(0.1)
        while myUsart0.any() > 0:
            rxData += myUsart0.read(1)
        print("myUsart0: " , rxData.decode('utf-8'))
    ```
cscの作法 その443

# 概要
cscの作法、調べてみた。
練習問題、やってみた。

# 練習問題
ComboBoxを配列で扱え。

# 方針
- new ComboBox[5]する。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/a8aaf333-8596-9eab-0a7d-5ef9c7c7e9b8.png)


# サンプルコード

```

using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Data;

namespace App
{
	public partial class Form1: Form {
		ComboBox[] comboBoxs;
		public Form1() {
			Text = "ComboBox";
			ClientSize = new Size(300, 300);
			DataTable dt = new DataTable();
			dt.Columns.AddRange(new DataColumn[] {
				new DataColumn("ID", typeof(int)),
				new DataColumn("Obj", typeof(string))
			});
			dt.Rows.Add(0, "");
			dt.Rows.Add(1, "バナナ");
			dt.Rows.Add(2, "マンゴー");
			dt.Rows.Add(3, "パパイア");
			dt.Rows.Add(4, "キウイ");
			comboBoxs = new ComboBox[5];
			for (int i = 0; i < this.comboBoxs.Length; i++)
			{
				comboBoxs[i] = new ComboBox();
				comboBoxs[i].Name = "ComboBox" + i.ToString();
				comboBoxs[i].Location = new Point(30, 10 + 30 * i);
				comboBoxs[i].DataSource = new BindingSource(dt, null);
				comboBoxs[i].DisplayMember = "Obj";
				comboBoxs[i].ValueMember = "ID";
				comboBoxs[i].SelectedIndex = -1;
			}
			Controls.AddRange(this.comboBoxs);
			Button button1 = new Button();
			button1.Location = new Point(100, 250);
			button1.Text = "test";
			button1.Click += new EventHandler(button1_Click);
			this.Controls.Add(button1);
		}
		private void button1_Click(object sender, EventArgs e) {
			string str = "0: " + comboBoxs[0].Text + " 1: " + comboBoxs[1].Text + " 2: " + comboBoxs[2].Text + " 3: " + comboBoxs[3].Text + " 4: " + comboBoxs[4].Text;
			MessageBox.Show(str);
		}
		[STAThread]
		public static void Main() {
			Application.Run(new Form1());
		}
	}
}





```


以上。
IS NOT IN GOROOTのエラーが発生した時の解決方法

## IS NOT IN GOROOTのエラーが発生した時の解決方法

### GoのAPIを開発していて、割と初期に発生し、少しハマったので、記事として残しておきます。<br>初学者や、久々にGo書いていて、色々忘れているって人に多いんじゃないかと感じたエラーでした。<br>※まあ自分が忘れてただけってものあるんですがwwwww

## 現象
#### GoのAPIを開発していて、以下のようなエラーが発生しました。

```
$ main.go:4:2: package go_project/internal/controllers is not in GOROOT (/usr/local/go/src/go_project/internal/controllers)
```

## フォルダ構成
```
GO_PROJECT
├── cmd
│   └── go_pro
│       └── main.go
└── internal
    └── controllers
        └── codemst_controller.go

```

## 原因
go.modのmoduleに設定されているルートパスを指定せずにフォルダ構成のパスでimportしようとしていた。<br>これで。Goのコンパイラが、Controllersのフォルダってどこやねん！となってエラーを吐いていた。


## 実際のコード
```cmd¥go_pro¥main.go
package main

import (
	"go_project/internal/controllers"
)

func main() {
	controllers.CodemstController()

}

```
    
```internal¥controllers¥codemst_controller.go    
package controllers

import (
	"fmt"
)

func CodemstController() {
	fmt.Println("Hello World")
}

```

```go.mod
module go_pro

go 1.20

```

## 修正後のコード
#### importのパスをgo.modのmoduleに設定されているルートパスを指定するように修正する。

```cmd¥go_pro¥main.go   
package main

import (
	"go_pro/internal/controllers"
)

func main() {
	controllers.CodemstController()

}

```

#### 分かってしまえば簡単なことですが、Goのコンパイル時の動作などを知らないと、ハマってしまいます。（自分だけ？？？）<br>自分もまだ完全に理解しているわけではないので、日々勉強していこうと思います。<br>誤りなどあれば、コメントにて指摘をお願いします。

#### 今回はこれで以上となります。
2023/9/5主にITとかセキュリティの記事

AIチャットボットを狙う「プロンプトインジェクション攻撃」　英当局が警告(9/3)
https://forbesjapan.com/articles/detail/65678

WordPressプラグイン21個に新たな脆弱性、確認とアップデートを(9/3)
https://news.mynavi.jp/techplus/article/20230903-2762478/

動機は？ジェミニ天文台、ハッキングされ活動停止中(9/3)
https://www.gizmodo.jp/2023/09/hackers-shutdown-two-observatories-north-south-gemini.html

中国ハッカーがウイグル族を標的に「偽の通信アプリ」を配布(9/3)
https://forbesjapan.com/articles/detail/65701

「ありえない」「スパイ事案としか...」関係者が異口同音に唸る「防衛省ハッキング事件」の謎(9/3)
https://gendai.media/articles/-/115617

PyPIパッケージマルウェア「VMConnect」に亜種、北朝鮮との関連する証拠発見(9/3)
https://news.mynavi.jp/techplus/article/20230903-2762624/

関係者が首をかしげる「防衛省ハッキング事件」で元情報幹部が指摘する「日米の極秘イントラネット回線へのハッキング」の可能性を探る(9/3)
https://gendai.media/articles/-/115618

ロシア軍ハッカー、狙いはウクライナ兵使うモバイル機器の作戦情報(9/3)
https://nordot.app/1070971866387694560

数十万人の中国人スパイ、暗躍する北朝鮮スパイ…『VIVANT』監修者・元公安警察官が明かす「日本というスパイ天国」のヤバすぎる実態(9/3)
https://gendai.media/articles/-/115158

勉強に戦略が必要なのは｢努力をしない｣ため(9/2)
https://news.nifty.com/article/magazine/12208-2532946/

規範示すべきNISCがサイバー攻撃時の情報共有を軽視、JPCERT/CCが指摘(9/4)
https://xtech.nikkei.com/atcl/nxt/column/18/00001/08341/

「技術解説を書くライターの副業があるんですか、どこで募集しているんですか？」(9/4)
https://xtech.nikkei.com/atcl/nxt/column/18/02518/00033/

長過ぎるLANケーブルは通信できない？(9/4)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/031600159/081700006/
🚀 「FlutterDude」が紹介します: Flutter がモバイル開発に最適な理由! 📱

![ux-indonesia-qC2n6RQU4Vw-unsplash.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552138/1bb6ef51-d732-f50f-afca-f1488d1e9c65.jpeg)


🎨 美しい UI: Flutter はカスタマイズ可能なウィジェットの豊富なセットを提供し、iOS および Android プラットフォーム全体で美しく一貫した UI を保証します。

⚡ 迅速な開発: Flutter の「ホット リロード」機能により、リアルタイムのコード変更が可能になり、開発サイクルが短縮され、生産性が向上します。

📦 単一のコードベース: 一度開発すれば、どこにでもデプロイできます! iOS と Android の両方に対応する 1 つのコードベースを作成することで、メンテナンスの労力と市場投入までの時間を最小限に抑えます。

🛠️ 豊富なライブラリ: 広範なライブラリ サポートにより、Flutter はアニメーション、ネットワーキングなどの機能をシームレスに統合できます。

   ウィジェットの再利用性: カスタム ウィジェットを構築するか、事前に設計されたウィジェットを使用して複雑な UI を作成し、開発を効率的かつ一貫性のあるものにします。

🌐 レスポンシブ レイアウト: Flutter のレスポンシブ デザイン原則により、アプリはさまざまな画面サイズや向きでも美しく表示されます。

🔄 プラットフォーム API: Flutter の「プラットフォーム チャネル」を使用してプラットフォーム固有の API に直接アクセスし、柔軟性とネイティブのようなパフォーマンスを提供します。

🚀 高性能: ネイティブ ARM コードへの Flutter のコンパイルにより高速な実行が保証され、スムーズで応答性の高いユーザー エクスペリエンスが可能になります。

🔍 表現力豊かな UI: Flutter のレイアウトとデザイン用の豊富なツールセットを使用して、クリエイティブな境界をなくし、ピクセル完璧なデザインを作成します。

🤝 強力なコミュニティ: 開発者の活気に満ちたコミュニティに参加し、知識、ライブラリ、共通の課題に対するソリューションを共有します。
Flutter を使用してモバイル開発ゲームを向上させましょう – 革新性とシンプルさが融合しています。 🚀📱 #FlutterDude #MobileAppDev #FlutterLove #UIUXMagic \
Docker化のMySQLサーバーが正常に起動してるかを簡単に確認できると思う僕が甘かった件

## TL;DR
Docker Composeとかでコンテナー化のMySQLサーバーに正常に接続できたらアプリを起動するという依存関係を実現したいのなら、下記のような`healthcheck`と`depends_on`構文を使ってください。

```yaml
app:
  container_name: app
  build:
    context: .
    dockerfile: Dockerfile
  ports:
    - '8080:8080'
  depends_on:
    mysql:
      condition: service_healthy
mysql:
  container_name: mysql
  image: mysql:8.0
  environment:
    MYSQL_ROOT_PASSWORD: password
  healthcheck:
    test: "mysqladmin ping -h 127.0.0.1 -u root -p$$MYSQL_ROOT_PASSWORD"
    timeout: 5s
    interval: 5s
    retries: 10
```

## 一時的に立ち上げられたMySQLサーバーによる惨事

いろんな記事は上記の`test`文が`["CMD", "mysqladmin" ,"ping", "-h", "localhost"]`と書いてあるが、それは実に大問題になる。

https://zenn.dev/sun_asterisk/articles/b4b17681d08018

https://blog.mtb-production.info/entry/2021/09/18/204107


MySQLコンテナーは起動する時にまず一時的なMySQLサービスを立ち上げて初期化プロセスをするので、もしこのタイミングに上記のテストコマンドが実行されたら、ヘルスチェックが成功になってしまう。でも本当なサービスがまだ起動してないので、MySQLに依存するコンテナーの起動は当然に失敗になるわけ。

## 一時的なMySQLサーバーと正式なMySQLサーバーにどんな違いがあるか

一時的なサーバーはローカルのsocket connectionしかサポートしていない。
正式的なサーバーはnetwork interfaceもlistenしている。

MySQLのクライエントは指定されるホストがlocalhostであれば自動的にsocket connectionで接続するので、`mysqladmin ping -h localhost`だと、成功しても一時的なサーバーに接続した可能性もあるので、ヘルスチェックの標準として頼れない。

## ドルが足りない環境変数

もしMySQLコンテナーにRootパスワードを指定したら、`mysqladmin ping`にはパスワードも必要になる。


```yaml
test: "mysqladmin ping -h 127.0.0.1 -u root -p$MYSQL_ROOT_PASSWORD"
```
でいいじゃない？

もし単純にシェルで実行すれば、確かにこれで問題なし。でも`docker compose`のYAMLであれば、`$MYSQL_ROOT_PASSWORD`を`$$MYSQL_ROOT_PASSWORD`を変更しなければならない。

```yaml
test: "mysqladmin ping -h 127.0.0.1 -u root -p$$MYSQL_ROOT_PASSWORD"
```

原因は[この前に記事で書いたことがある](https://qiita.com/akarei/items/b52edf9fe6d49b3a13b6)。


## テスト文のフォーマット
ちなみに、ここには`["CMD", "command", "argument"]`のようなフォーマットじゃだめそう。なぜなら、CMDはEXECでコマンドを実行するので、コマンド内の環境変数は普通の文字列として扱ってしまう。`["CMD", "mysqladmin" ,"ping", "-h", "127.0.0.1", "-p$$MYSQL_ROOT_PASSWORD"]`が`mysqladmin ping -h 127.0.0.1 -p'$MYSQL_ROOT_PASSWORD'`になる。つまりここで指定されたRootパスワードが`$MYSQL_ROOT_PASSWORD`そのままであるわけ。

`[]`のようなリストフォーマットにこだわれば、`CMD-SHELL`を使ってください。

```YAML
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -u root -p$$MYSQL_ROOT_PASSWORD"]
```

[ドキュメント](https://docs.docker.com/compose/compose-file/compose-file-v3/#healthcheck)によると、

>test must be either a string or a list. If it's a list, the first item must be either NONE, CMD or CMD-SHELL. If it's a string, it's equivalent to specifying CMD-SHELL followed by that string.
LXDのコンテナのポートを外部に公開する

## 目的
LXDコンテナで、docker exposeに値する様な設定をしたい

## 設定
構文
```bash
lxc config device add <container_name> <proxy_name> proxy  listen=tcp:<host_ip>:<host_port> connect=tcp:<container_ip>:<container_port> bind=host
```

例
```bash
lxc config device add ubuntu-lamp ubuntu-lamp-proxy proxy  listen=tcp:192.168.219.40:80 connect=tcp:10.107.73.3:80 bind=host
```

## 設定削除
構文
```bash
lxc config device remove <container_name> <proxy_name>
```

例
```bash
lxc config device remove ubuntu-lamp ubuntu-lamp-proxy
```
GitHub Actions 動作時に husky install を実行しないようにする

## 概要
ローカル環境で Git hooks の操作をする際に非常に便利な [Husky](https://typicode.github.io/husky/) なんですが、ある日 Husky を導入しているリポジトリで GitHub Actions を動かすと、なぜか Actions 上でも Husky が動いていることがわかりました。

こちらの37行目以降が該当のログです。`husky install` が実行されていることがわかります。
![スクリーンショット 2023-09-04 1.59.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70638/4b0335a2-4c74-9a6c-5ff9-b525dc9101e1.png)

これといって困っているわけではないですが、CI上では Husky を動かす必要がないので止められるなら止めたい、というのが今日の話です。

## 原因

Husky のインストール時に package.json の `prepare` に `husky install` が自動で追加されます。そのため、npm のライフサイクルに入ってしまって、CI上での npm install (ここでは yarn install)時に動いてしまうようです。

```json:package.json
  "scripts": {
    "prepare": "husky install"
  }
```

## 対応方法

公式に書いてありましたが、`HUSKY` という環境変数に 0 をセットしておけばインストールは動かないそうです。ということでこれをやってみます。

https://typicode.github.io/husky/guide.html#with-env-variables

> You can set `HUSKY` environment variable to `0` in your CI config file, to disable hooks installation.


## 環境変数を追加

私の場合は、GitHub Actions の設定ファイルに以下のように環境変数を追加しました。

```diff
    - name: Install dependencies
      run: yarn install --frozen-lockfile
      shell: bash
+     env:
+       # CI上では husky を動かさないようにする
+       # https://typicode.github.io/husky/guide.html#with-env-variables
+       HUSKY: '0'
```

## 確認

`husky - HUSKY env variable is set to 0, skipping install` の文言が表示され、無事意図通りインストールがスキップされました。

![スクリーンショット 2023-09-04 2.12.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70638/0debf123-e989-51f9-79ad-c34ce825baee.png)

## 感想
そもそも GitHub Actions 上で husky install が動いていたことに気づいていない(私みたいな)、あるいは大勢に影響ないので大して気にしていない、という場合も往々にしてありそうです。

気になった方は参考にしてみてください。
Base64のJavaScript内での動作

![Base64-in-JavaScript.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552100/2b9cda2e-5569-5e49-aeda-80f41dec8b9c.png)

Base64は、バイナリデータをテキスト形式で表現する広く利用されるエンコーディングテクニックです。それはJavaScriptでさまざまな目的に簡単に利用できます。この記事では、Base64がJavaScript内でどのように動作し、それを効果的に使用する方法について探求します。

Base64の簡単な概要
Base64は、バイナリデータをテキスト文字に変換する方法です。これにより、XML、JSON、またはURLなどの形式でデータを送信または保存しやすくなります。Base64は通常、大文字と小文字の英字、数字、および'+'や'/'などの特殊文字を含む特定の文字セットで動作します。

JavaScriptでのBase64の基本
JavaScriptでは、[Base64](https://b64encode.com/)エンコーディングには組み込みのbtoa()関数を使用し、デコードにはatob()関数を使用します。

テキストをBase64にエンコードする：
let originalText = "This is a sample text.";
let base64Encoded = btoa(originalText);
console.log(base64Encoded);
このコードはテキストをBase64にエンコードし、その結果をコンソールに表示します。btoa()関数はテキストをBase64にエンコードします。

Base64のデコード
Base64エンコードされたデータを元のバイナリ形式にデコードするには、atob()関数を使用します。

Base64をデコードする：
let base64EncodedData = "VGhpcyBpcyBhIHNhbXBsZSB0ZXh0Lg==";
let originalData = atob(base64EncodedData);
console.log(originalData);
このコードはBase64エンコードされたデータをデコードし、元のテキストデータをコンソールに表示します。atob()関数はBase64をデコードします。

結論
JavaScriptでのBase64エンコードおよびデコードは簡単です。このテクニックを使用することで、バイナリデータをテキストデータに変換し、さまざまなアプリケーションでデータの送受信や保存を簡素化できます。
Weston on Ubuntu 22.04

# 諸事上でネイティブwaylandが必要になったので

記事を書く上でwayland環境でリモートディスプレイ（waypipe）を試す必要が出てきました。
現状メインで使っているswayで仮想マシンをいくつ方立ててもいいのですが、せっかくなので別の環境も使ってみようかと思います。

wayland対応を謳っているWindowManagerは多々ありますが、xwaylandも入ってきちゃうので、注意が必要です。
で、ざっとみxwaylandが入ってこなさそうなwestonを使ってみようかなと思ったのですが、、微妙にトラブりました。
解決法をメモっときます。

# Ubuntu server + apt weston

apt install --no-install-recommends weston。
これで起動してみると、、こんなエラーで起動できません。
ちなみにそのまま実行するとエラー出力で改行されちゃって、詳細が読めません。
なので、一回ファイルにログ吐き出してから見てます。

```
$ weston >./log 2>&1 
$ cat ./log
Date: 2023-09-04 UTC
[14:57:47.904] weston 9.0.0
               https://wayland.freedesktop.org
               Bug reports to: https://gitlab.freedesktop.org/wayland/weston/issues/
               Build: 9.0.0
[14:57:47.904] Command line: weston
[14:57:47.904] OS: Linux, 6.2.0-31-generic, #31~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Wed Aug 16 13:45:26 UTC 2, x86_64
[14:57:47.904] Starting with no config file.
[14:57:47.904] Output repaint window is 7 ms maximum.
[14:57:47.904] Loading module '/usr/lib/x86_64-linux-gnu/libweston-9/drm-backend.so'
[14:57:47.905] initializing drm backend
[14:57:47.908] logind: session control granted
[14:57:47.909] using /dev/dri/card0
[14:57:47.909] DRM: supports atomic modesetting
[14:57:47.909] DRM: supports GBM modifiers
[14:57:47.909] DRM: supports picture aspect ratio
[14:57:47.909] Loading module '/usr/lib/x86_64-linux-gnu/libweston-9/gl-renderer.so'
pci id for fd 16: 1b36:0100, driver (null)
MESA-LOADER: failed to open qxl: /usr/lib/dri/qxl_dri.so: cannot open shared object file: No such file or directory (search paths /usr/lib/x86_64-linux-gnu/dri:\$${ORIGIN}/dri:/usr/lib/dri, suffix _dri)
MESA-LOADER: failed to open zink: /usr/lib/dri/zink_dri.so: cannot open shared object file: No such file or directory (search paths /usr/lib/x86_64-linux-gnu/dri:\$${ORIGIN}/dri:/usr/lib/dri, suffix _dri)
MESA-LOADER: failed to open kms_swrast: /usr/lib/dri/kms_swrast_dri.so: cannot open shared object file: No such file or directory (search paths /usr/lib/x86_64-linux-gnu/dri:\$${ORIGIN}/dri:/usr/lib/dri, suffix _dri)
MESA-LOADER: failed to open swrast: /usr/lib/dri/swrast_dri.so: cannot open shared object file: No such file or directory (search paths /usr/lib/x86_64-linux-gnu/dri:\$${ORIGIN}/dri:/usr/lib/dri, suffix _dri)
[14:57:47.909] failed to initialize egl
[14:57:47.909] fatal: failed to create compositor backend
Internal warning: debug scope 'drm-backend' has not been destroyed.

```

エラーが出ている/usr/lib/dri/...は、たしかに入ってません。
エラーでググってもあまりどんぴしゃの記載はないのですが、とりあえずMESAのドライバーがない、で事象はあってるんだと思います。
なので、思考停止して。。

# 解決策

```
$ apt search mesa
...
```

それっぽいのがいたので、、

```
$ sudo apt install libgl1-mesa-dri
```

これで、westonで起動できるようになりました。

ちなみにこれ、--no-install-recommendsをつけなければ、入ってくるパッケージでした。
。。余計なことしたなぁ、、まぁさておき。

# Wayland,,,じゃない？

で、起動するんですが、、あれ、、？
tty?

![20230905_00h26m01s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/5ed8e7f3-5f4d-e40c-89ab-0547bb709bf3.png)

# とりあえず

今日はここまでで。。
もうちょっと調べないとだめだ。
一時的な電子メール Web サイトのトップ 10

一時的な電子メール Web サイトのトップ 10

![temp-mail.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552079/a47ac495-2d16-bef2-b805-e023e94b4c63.jpeg)

今日のデジタル時代において、一時的な電子メール サービスは、オンライン プライバシーを維持し、スパムを回避し、オンライン登録を簡素化するための重要なツールとなっています。 利用可能なオプションは数多くありますが、NoopMail.org はユーザーの間でナンバー 1 の選択肢として際立っています。 一時的な電子メール Web サイトのトップ 10 を見てみましょう。NoopMail.org がトップの座を占めています。

1. NoopMail.org (https://noopmail.org):

NoopMail.org は、一時的な電子メール分野の主要なプレーヤーです。 ユーザーフレンドリーなインターフェイスと、電子メールの迅速な生成、無制限の受信トレイ ストレージ、堅牢なスパム フィルターなどの幅広い機能を提供します。 これは、信頼できる一時的な電子メール ソリューションを求める多くのユーザーにとって頼りになる選択肢です。

2. TempMail.net
3. 10MinuteMail.com
4. GuerrillaMail.com
5. Mailinator.com
6. MailDrop.cc
7. FakeMail.net 
8. Getnada.com
9. MyTemp.email
10. TempMailAddress.com
BigQueryのストレージ保存費用を予測するためにクエリをたたいてみた

<h1>BigQueryのストレージ保存費用を把握したい


Big Queryを利用した際のストレージ保存料金を計算するために、どのようなクエリを実行すればわからなかったため、下記ドキュメントを参考にしました。
<br>

https://cloud.google.com/bigquery/docs/information-schema-table-storage?hl=ja

上記ドキュメントについてざっくり説明すると、
**INFORMATION_SCHEMA.TABLE_STORAGE** ビューには、
圧縮状態・非圧縮状態のストレージ容量 (の予測値) が格納されているので、そちらに料金表の価格を乗算して見積もることが可能です。

以下、具体的な手順です。
<br>
<br>

<h2>実行権限について


SQL を実行するには権限が必要です。もう少し具体的に言うと、対象の BQ リソースがあるプロジェクトではなく、そのプロジェクトが属する組織 (Organization) に対して以下の権限を持つ必要があります。

- bigquery.tables.get
- bigquery.tables.list
<br>

次の各 IAM 事前定義ロールには、上の権限が含まれています。

- roles/bigquery.admin
- roles/bigquery.dataViewer
- roles/bigquery.dataEditor
- roles/bigquery.metadataViewer

<br>
<br>



<h2>SQLを実行する

Big Queryのワークスペース内で下記クエリを書いて、SQLを実行します





~~~
SELECT
  project_id,
  -- logical_gb  : Total number of logical (uncompressed) bytes in the table (GB)
  -- physical_gb : Total number of physical (compressed) bytes used for storage (GB)
  ROUND(SUM((TOTAL_LOGICAL_BYTES  / POW(1024, 3))),2) AS logical_gb,
  ROUND(SUM((TOTAL_PHYSICAL_BYTES / POW(1024, 3))),2) AS physical_gb,
  -- logical_billing_model  : monthly storage costs that use a logical billing model (USD)
  -- physical_billing_model : monthly storage costs that use a physical billing model (USD)
  ROUND(SUM(((ACTIVE_LOGICAL_BYTES  / POW(1024, 3)) * 0.023) + ((LONG_TERM_LOGICAL_BYTES  / POW(1024, 3)) * 0.016)),3) AS logical_billing_model,
  ROUND(SUM(((ACTIVE_PHYSICAL_BYTES / POW(1024, 3)) * 0.052) + ((LONG_TERM_PHYSICAL_BYTES / POW(1024, 3)) * 0.026)),3) AS physical_billing_model
FROM
  `region-asia-northeast1`.INFORMATION_SCHEMA.TABLE_STORAGE_BY_ORGANIZATION
GROUP BY
  project_id
ORDER BY
  project_id
 ~~~

<br>
<br>
<br>
今回、サンプルの画像を持ってこれなかったので、上記クエリを打ち込むと下記表組みのような内容が抽出されます。
<br>

|product_id|logical_gb|physical_gb|logical_billing_model|physical_billing_model
|---|---|---|---|---|
|------|3.14|0.74|0.062|0.005|


<br>

この場合、論理 (非圧縮状態) で3.14GB--> 0.062ドルだったものが、物理 (圧縮状態) で 0.74GB --> 0.005ドル、のコストになる計算です。

<br>

バイト合計数と予測費用の詳細については下記を参考にしてください。

|項目名|単位|内容|
|---|---|---|
|logical_gb|GB|テーブルまたはマテリアライズド ビューの論理（非圧縮）バイトの合計数
physical_gb|GB|ストレージに使用される物理（圧縮）バイトの合計数（アクティブ、長期、タイムトラベル（削除または変更されたデータ）バイトを含む）
logical_billing_model|USD|論理課金モデルを使用した場合の月間ストレージ予測費用
physical_billing_model|USD|物理課金モデルを使用した場合のストレージ予測費用


<h2>詳細



論理課金モデルを使用するデータセットの場合、月間ストレージ費用は、次のように予測できます。
((ACTIVE_LOGICAL_BYTES value / POW(1024, 3)) * アクティブな論理バイト料金) + ((LONG_TERM_LOGICAL_BYTES value / POW(1024, 3)) * 長期論理バイトの料金)

物理課金モデルを使用するデータセットの場合は、ストレージ費用を次のように予測できます。
((ACTIVE_PHYSICAL_BYTES value / POW(1024, 3)) * アクティブな物理バイト料金) + ((LONG_TERM_PHYSICAL_BYTES value / POW(1024, 3)) * 長期物理バイトの料金)


※
単価とリージョン（データセットのロケーション）は東京のものにハードコードされているので、他のリージョンで利用する場合は適宜修正してください。

なお[料金のページ](https://cloud.google.com/bigquery/pricing#storage) は言語を English にしないと物理ストレージ料金が出力されませんでした。




まとめ

BQ 使用してストレージ保存費用をシミュレーションする方法をご紹介しました。
是非参考にしてみてください。
【Active Record】データ処理のアンチパターン①


:::note info
Active Recordデータ処理のアンチパターンについて整理されたスライドを見つけたので、学習のためにまとめました。
:::

今回読んだスライドがこちらです。
3つの事例と6つのアンチパターンを紹介していただいているので、1つずつ見て整理して行きます。

https://blog.toshimaru.net/rdm2018-active-record-anti-patterns/

---

:::note info
前提事項
・User has many Postsな関係のUserモデル＆Postモデル
・User10万件、Post50万件のデータが登録されている
・データベースの最適化は考慮しない
:::
#### スキーマ定義
```ruby
create_table "posts", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.bigint "user_id, null: false
    t.string "title"
    t.text "content"
    t.integer "like_count", default: 0, null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["user_id"], name: "index_posts_on_user_id"
end

create_table "users", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.string "email", null: false
    t.string "name", null: false
    t.integer "point", default: 0, null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_users_on_email", unique: true
end

add_foreign_key "posts", "users"
```


### 事例1 全ユーザの中から、2017以降の登録ユーザへ100ポイント付与する

#### アンチパターン
```ruby
User.all.each do |user|
  if user.created_at >= Date.new(2017)
    user.point += 100
    user.save
  end
end
```
:::note warn
**All Each Pattern**
Model.allで、テーブルの全レコードを取得した後に、その結果をeachでループさせること。
:::

|問題点|解決策|
|:------------|:--|
|全件取得でメモリが逼迫。そもそも全件取得する必要あるのか？|取得件数をフィルター（all→where）|
|ループ回数が増えるのでCPUリソースも消費|少しずつUserを取得してメモリフレンドリーな処理に　（each→fnd_each）|

#### 改善後ソースコード
```ruby
User.where("created_at>=?", Date.new(2017)) # 取得件数のフィルタリング
    .find_each do |user|                    # 少しずつレコードを取得する
        user.point += 100
        user.save
end
```
:::note warn
**N＋1　Update Queries Pattern**
:::

|問題点|解決策|
|:------------|:--|
|1回Select＋N回Updateのクエリが走る |複数レコードを一括で更新する(update→update_all)|
|Nの数が多くなるほどパフォーマンスが悪化する|update_allはバリデーションやコールバックが実行しないので、適切な処理を加えた上で使う必要がある。|

#### 改善後ソースコード
```ruby
User.where("created_at>=?", Date.new(2017))
    .update_all("point = point + 100")
```


:::note info
まとめ
・全件取得はなるべく避け、事前にフィルタリングできないか検討する
・ループ処理はCPUリソースを消費するので、find_eachメソッドなどで少しずつ処理する
・update_allを使用することで、クエリの発行回数を削減する
:::
【Linux】指定した文字列が含まれていないファイルのパスを取得する

## `grep`コマンドで取得

`grep`コマンドを使用して内容に特定の文字列を含まないファイルのパスを取得するには以下のように実行します。  

```zsh
grep -Lr '検索する文字列' 対象のパス
```

* `-L`
検索する文字列が含まれていないファイルのパスのみ表示する。
* `-r`
ディレクトリを指定した場合にサブディレクトリ内のファイルも含めて検索する。

以下のようにファイルを作成し実際に実行してみます。

```zsh
$ tree
.
└── sample
    ├── example.txt
    └── test.txt

$ cat ./sample/example.txt
ABCDE

$ cat ./sample/test.txt
12345

```

```zsh
$ grep -Lr '1' ./sample
./sample/example.txt
```

`1`が含まれていない`example.txt`のパスが出力されました。
今更ながらVMware Explore 2023のことを

https://gokusan.hatenablog.com/
ブログをQiitaに移行しました。

移行後一発目のブログは、VMware Explore 2023 in LasVegasについて、超遅ればかつ、取り留めなく書こうと思います。

## そう。Las Veagasなんだよ。
会社の厚意で、行かせてもらえることになったVMware Explore 2023ですが、今年はアメリカ合衆国 ネバダ州ラスベガスで行われました。

何を隠そう、海外渡航は初な私なもので、**不安と恐怖が8割・残り2割**が楽しみという完全にマイナス寄りなスタートでした。

今年は、VENETIANホテルで行われましたが、とにかくデカい。
日本じゃできない土地の使い方をしています。
![PXL_20230821_161455068.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552050/45d6cb72-b854-550a-ff8d-6df8ec9f8c1a.jpeg)

![PXL_20230821_162212492.MP.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552050/486e283b-3253-0760-3dfa-785cac74ea1e.jpeg)

## 個人的に気になったのは
今年の発表で、おそらくたくさんの方が「おっ」と思われたのはやはり**Private AI**だったのではないでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552050/c26f244f-90be-f876-6e0d-b872b57c7bef.png)

「VMもついにAIに手を出したのか・・・！」

という印象を強く受けましたね。
ChatGPTに始まり、生成AIがここまで短期間で世に浸透したのには衝撃を受けたものですが、その波がVMwareにまで来るとは…

>VMware は NVIDIA と協力して、VMware Private AI Foundation with NVIDIA を提供しています。このソリューションにより、企業は大規模な言語モデルを微調整し、社内で使用するためのより安全でプライベートなモデルを生成し、生成 AI をサービスとしてユーザーに提供し、大規模な推論ワークロードをより安全に実行できるようになります。このソリューションは VMware Cloud Foundation と NVIDIA AI Enterprise 上に構築されており、次の利点を提供します。

各企業にプライベートな生成AI環境を提供し、「プライバシー」や企業の「規制遵守」といった課題に適応できる、というわけですね。
そして、そのPrivate AI環境を構成するためのインフラ（基盤/ネットワーク/セキュリティなど)として、VMware製品もいけるんやで(ﾆｯｺﾘ)というわけですね。
vSphereという圧倒的な市場シェアからの横展開はいつもながら見事なものです。

### ひっそりとVMware Cloud周りもアップデートが。
vSAN MAXやNSX+など、基盤周りのアップデートもちらほらと発表されておりました。
情報の渦と英語に吞まれそうでしたが、発表当時にはVMware Blogでも情報が細かに公開されておりましたね。

https://blogs.vmware.com/cloud/2023/08/22/announcing-vmware-cloud-on-aws-advanced-subscription-tier/

>So, What’s included in VMware Cloud on AWS: Advanced host purchase?
With the purchase of VMware Cloud on AWS: Advanced subscription tier host, customers will get:
>VMware SDDC software
Bare metal AWS EC2 instance
vCenter Management
VMware HCX
Tanzu services
>VMware Aria Automation
VMware Aria Operations
VMware Aria Operations for Logs
VMware Aria Migration (30 days free trial)
Advanced security capabilities: Context-aware microsegmentation (L7 DFW AppID), Distributed FQDN allowlisting, User Identity-based Firewall (IDFW),
NSX+ Policy Management

はい。
あのVMware Cloud on AWSに「Advanved Subscription Tier」なるものが出来ました！
主にAria(旧vRealize)が使えるようになったようですね。

vRealize 時代はよく「LogInsight」を使っておりましたが、そちらも含まれるようです。（for Logsってついてるやつです）

https://vmc.techzone.vmware.com/resource/vmware-cloud-on-aws-advanced-subscription-tier

「マジで！？」と思ったのは、価格が変わらない、という点です。
思わず二度見しましたが、QAにもばっちり書いてる・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552050/ee683972-029a-3e92-f343-cdda74b52fab.png)

私も中々vRealize時代からVMwareの運用製品はお客様におすすめできていなかったのですが、今回のExploreでもAriaをプッシュしている印象を強く受けましたので、これから頑張って勉強しないとです。。
JUnitで現れるエラーたちの対処法

序章
 -

JUnitで現れるエラーさんたち。
よく「またあなた（エラー）ですか」という気持ちになってしまうので、備忘録を作成しておく。
（そもそも出さないようにしなさいって思った方、きっと明日は晴れるでしょう）

以下から解説
 -

- NullPointerException
  -  どこか値抜けてるよ！値がうまく入っていない！
  -  作ったテストコードに抜けがある or ロジックのほうに問題がある
  -  必須になｔっている値を見落としてるとか。。。
  -  アノテーションのAutowiredとか、テストクラスに不足していたりしない？
  -  superクラスでAutwiredしているのに、さらにAutowiredするとnullぽになることがある。継承しているクラスのAutowired消せば大丈夫。
- NoSuchColumnException
  - テーブルのカラムがDB上に無いときに起こりやすい
  - Excelにテーブルを書いて読み込ませてる場合、カラム名間違っていたりしない？
- NoSuchMethodException
  - メソッドの引数はあっとるかい？合っていない可能性がある。。。
- MockitoException: Only void methods can doNothing()!
  - 和訳したとおり、doNothingはvoidにしか使えない。
  - voidメソッド以外をdoNothingしたい場合、doReturn等を利用しましょっ
- IllegalStateException: Duplicate key テーブル名...
  - 重複しちゃいけないキーが重複している！読み込ませたデータを見直すべし！
  - 経験談：nullぽエラーの下に潜んでいることがあるよっ
- TooLittleActualInvocations
  - verifyを使ったとき、設定した回数が誤っている可能性あり。コンソール内に表示されたヒント参照にすれば直せる。

終わりに
 -

Qiitaに書き起こしている間、よくJUnitエラーをメモに残して対処していた日々を思い出しました。
エラー解決できなかった時、助ってくださった先輩方、とても助かりました。ありがとうございました。

この記事を見つけたくださったJUnitエラーに困っている方、頑張ってくださいね...！