Qiita記事をローカル管理するツールが入門としてよかった話

概要

Goの入門としてQiitaをローカル管理するツールを作った。
リポジトリは以下。
https://github.com/ma-bo-do-fu/qsync
今回はその感想をメモしておく。対象読者はGo言語やツール開発初心者。

環境

$go version
go version go1.10.3 darwin/amd64

モチベーション

  • Goの練習したい
  • Qiita記事をGithub管理したい
  • ドキュメント管理をCIに載せたい

作ったもの

詳細は下記参照。
https://github.com/ma-bo-do-fu/qsync/blob/master/README.md
概要だけ記載する。

$qsync pull

すべての投稿を指定した場所に保存する。

$qsync push /path/to/entry

保存した投稿を更新する。

$qsync post

新規に投稿する。

入門としてよかった点

題材が練習としてちょうどよかった。 今回のツールを通して以下の処理について学ぶことができた。

  • APIクライアント
  • josnやyamlエンコードとデコード
  • 文字列操作
  • ファイル読み書き
  • 日付操作

問題点

画像添付できない

画像添付用のAPIがないので画像が添付できない状態。
運用としてローカルで画像保存用のディレクトリ(例:YYYY/mm/dd/images)を作ってそこで管理し、記事公開時に改めてブラウザ側で添付するなどか…
Qiitaの画像はS3で管理されているので、

$qsync attach 記事ID /path/to/image

とかでS3のURLが返ってきたらローカルで作業が完結できそう。

マークダウンの表示が異なる

VSCodeのマークダウンプレビューととQiitaの編集画面とで表示が異なる。 結局微調整のためにブラウザで編集することに…

感想

  • テストを書かずに開発するのはつらい
    とりあえず動くものを作ろうとテストを書かずに開発したら苦労した。次はテストの書き方を覚える予定。
  • 毎回go build/go installをするのが大変
    コード変更したら自動でビルドとインストールが走るようにしたい。
  • プロジェクトの名前が被っていた
    ツールを作るときはGoogleGithubで検索して被っていないか調べたほうが良い。
  • rangeの書き方が馴染んだ
    tour of goをやっているときにrangeの書き方に戸惑ったが、ツールを書いていたら馴染んだ。
  • gometalinterを早めに入れればよかった
    linterは開発初期から入れるべき。後から入れると修正が大変。
  • ちゃんと設計しないと後からつらくなる
    README駆動開発という言葉もあるように、最初に要件定義を書くと全体の見通しが立ちやすいと思う。

何かのサービスのAPIクライアントを作るのは、その言語に初めて触れるときに良い練習になると感じた。 新しい言語を学びたいけど作るものに困っている方はAPIクライアントにチャレンジしてみるとよいかもしれない。

php artisan migrateでautoload.phpがなくて失敗する

環境

$ php -v
PHP 7.1.10 (cli) (built: Aug 22 2018 18:45:08) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
    with Xdebug v2.6.1, Copyright (c) 2002-2018, by Derick Rethans

発生したエラー

$php artisan migrate

Warning: require(/var/www/app/bootstrap/../vendor/autoload.php): failed to open stream: No such file or directory in /var/www/app/bootstrap/autoload.php on line 17

状況

  • /var/www/app/bootstrap/../vendor/autoload.phpが存在しない
  • vendor/は存在する

原因究明

$composer install -vvv

とすることでcomposer installデバッグログが見れる。
すると下記のようなエラーが(docker-comopseで実行していた)

app_1    | 
app_1    |                                                                 
app_1    |   [RuntimeException]                                            
app_1    |   /var/www/app/vendor does not exist and could not be created.  
app_1    |                                                                 
app_1    | 
app_1    | Exception trace:
app_1    |  () at phar:///usr/bin/composer.phar/src/Composer/Util/Filesystem.php:186

解決方法

プロジェクトルート(今回は/var/www/app/)に書き込み権限を与えて解決

IntelliJがシステム環境変数を読み込むタイミングについて

概要

IntelliJがシステム環境変数を読み込むタイミングはIDE起動時。 途中でシステム環境変数を設定した場合はIDE再起動すること。

環境

$go version
go version go1.10.3 darwin/amd64

IntelliJ IDEA 2018.2.1 (Ultimate Edition)
(Goのプラグインを入れている)

再現手順

  1. HOGE="fuga"という環境変数を設定
  2. 以下のコードをIntelliJでctrl+shift+dでデバッグ
package main

import (
    "fmt"
    "os"
)

func main() {
    hoge := os.Getenv("HOGE")
    fmt.Println(hoge)
    fmt.Println("end")
}
  1. 出力結果
end

対応

IDEを再起動する。

感想

焦ってNode.jsで同じコードを書いて確認した。 go runしたらちゃんとシステム環境変数が読み込まれるので、IDEに問題があることに気づけた。

TODO

システム環境変数を更新したら毎回再起動するのは面倒なのでなにかいい方法がないか調べる。

vagrant up時にThe box 'bento/centos-6.8' could not be foundと表示される

問題

vagrant upしようとすると下記メッセージが出て失敗する。

$vagrant up
Bringing machine 'webserver' up with 'virtualbox' provider...
Bringing machine 'database' up with 'virtualbox' provider...
==> webserver: Box 'bento/centos-6.8' could not be found. Attempting to find and install...
    webserver: Box Provider: virtualbox
    webserver: Box Version: >= 0
The box 'bento/centos-6.8' could not be found or
could not be accessed in the remote catalog. If this is a private
box on HashiCorp's Atlas, please verify you're logged in via
`vagrant login`. Also, please double-check the name. The expanded
URL and error message are shown below:

URL: ["https://atlas.hashicorp.com/bento/centos-6.8"]
Error: The requested URL returned error: 404 Not Found

https://atlas.hashicorp.com/bentohttps://app.terraform.io/bento にリダイレクトされたので表示されているURLが古いっぽい。

解決方法

vagrantのバージョンをあげる。
アップデート前

$vagrant --version
Vagrant 1.9.3

アップデート後

$vagrant --version
Vagrant 2.1.2

CircleCI上でDockerfileのCMDが動かない

問題

CircleCI上でDockerイメージを使うとDockerfileのCMDが動かない。 ローカルでDockerコンテナを起動するとCMDが動く。

原因

最初のコンテナはcommandを書かないとエントリポイントが動かない https://circleci.com/docs/2.0/configuration-reference/#docker

For primary container (listed first in the list) if no command is specified then command and image entrypoint will be ignored, to avoid errors caused by the entrypoint executable consuming significant resources or exiting prematurely. At this time all steps run in the primary container only.

以下のようにDockerイメージをビルドしてコンテナに入ると、エントリポイントのスクリプトが動いている事がわかる。

$ cat Dockerfile 
FROM selenium/standalone-chrome
$ docker build . -t test:test
…
Successfully built 251941c07ece
Successfully tagged test:test
$ docker run -itd 251941c07ece
2848233eeaed57f855915a9046836f0f193d6bea71daa231df95203d8fbfac09
$ docker exec -it 2848233eeaed57f855915a9046836f0f193d6bea71daa231df95203d8fbfac09 /bin/bash
seluser@2848233eeaed:/$ ps auxw
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
seluser      1  0.2  0.1  20980  3332 pts/0    Ss+  15:44   0:00 /bin/bash /opt/bin/entry_point.sh
seluser     10  0.0  0.0   4500  1616 pts/0    S+   15:44   0:00 /bin/sh /usr/bin/xvfb-run -n 99 --server-args=-screen 0 1360x1020x24 -ac +extension RANDR java -jar /opt/selenium/selenium-server-standalone.jar
seluser     21  0.2  2.0 213644 41396 pts/0    Sl+  15:44   0:00 Xvfb :99 -screen 0 1360x1020x24 -ac +extension RANDR -nolisten tcp -auth /tmp/xvfb-run.JaVrPQ/Xauthority
seluser     26  5.8  2.5 2968504 51176 pts/0   Sl+  15:44   0:01 java -jar /opt/selenium/selenium-server-standalone.jar
seluser     46  0.7  0.1  21188  3668 pts/1    Ss   15:44   0:00 /bin/bash
seluser     53  0.0  0.1  37360  3228 pts/1    R+   15:44   0:00 ps auxw

エントリポイントをたどると以下のようになっている

しかし、CircleCI上で動かすと、selenium-server-standaloneなどが動いていないことが確認できる。

config.yml

version: 2
jobs:
  build:
    docker:
      - image: selenium/standalone-chrome
    steps:
      - checkout
      - run: ps auxw

workflows:
  version: 2
  build_and_test:
    jobs:
      - build

f:id:mMQnaZ7vL2DWkoU:20180712004910p:plain

対応

config.ymlにcommandを追加する。

version: 2
jobs:
  build:
    docker:
      - image: selenium/standalone-chrome
        command: ["/opt/bin/entry_point.sh"]
    steps:
      - checkout
      - run: ps auxw

workflows:
  version: 2
  build_and_test:
    jobs:
      - build

LTであんまりふざけすぎると伝えたいことが伝わらないというはなし

以前勉強会でLTをしたが、ふざけすぎて伝えたいことがあまり伝わらなかったように思うのでメモ。

LT内容

「一年間コードレビューを受けてみて、どんなコメントがつくとつらかったか。それを解決するためにどうしたか。」ということを話した。
要約すると、

  • 静的解析のルールが甘かったので、静的解析で解決できる指摘をたくさん受けてしまった。現在は自分用のルールを追加して使っている。
  • 設計の大幅な変更の指摘を受けることがあった。AtomのTeletypeなどで、リアルタイムのレビューをして、設計段階からチームに共有することで解決できるのではないか。
  • 理由のない指摘があったので、レビュアーになるときはなぜよくないコードなのか論理的な説明をするように心がけようと思った。

ということを言いたかった。

反省点

「こんなコメントが付いて、それに対して自分はどう思う」ということを、おどけたような感じで発表した。
しかし、少しふざけて大げさにLTしたので、うまく伝わらなかったかもしれない。
具体的には、レビューがいつもつらい、いまもつらいと思われたような印象を受けた。
そんなことはなく、つらいこともあったが少しずつ改善していますよ、ということを伝えたかった。

学んだこと

懇親会含め話に出たことを箇条書きにする

  • コードレビューは運用するのがむずかしい
  • とくにチーム内にスキル差があるとむずかしい
  • 静的解析は大事、静的解析をとおったもののみコードレビューする
  • 静的解析のルールは古くなったり、過不足が出てくるので、定期的に見直す事が必要
  • コードレビューの目的を明確にする
  • プログラムを新規作成するときは、設計をドキュメントに残す
  • 新人がプログラムを新規作成するときは、ペアプログラミングなどで、設計段階からチームメンバーに共有するとよい
  • 複数人で開発しているとき、レビュアーはレビュイーAによくないコードの理由を説明しており、レビュイーBのレビューをおこなうときに、前に一度説明したと勘違いして理由を書いていないパターンがあるかもしれない

LT後の質疑応答で、進行予定の時間をオーバーするほどたくさんの意見が出た。コードレビューネタはみんな好きだし、盛り上がるなと感じた。

Visual Regression Testについてのメモ

Visual Regression Test(回帰テスト)を実施することになったので、自分用にメモしておく

Node.jsでWebアプリを開発している想定

Visual Regression Testとは

ビューに崩れがないか確認するテスト。 開発を進めていくと、意図しないビューの変更が加わる事があるので、それを防ぐことを目的とする。

以下は、自チーム用の方針。

いつおこなうか

毎日定時に実行

正のビューについて

ビューに崩れがないか確認する場合、比較対象が必要になる。これを正のビューと呼ぶこととする。 テストの流れは以下のようになる。 1.正のビューを用意する。 2.テスト対象のビューと正のビューを比較し差分を検出する。

  • 何を正のビューとするか
    本来ならばデザイン時に正のビューを作って用意することが望ましいが、現状ないので、最新バージョンのものを正のビューとする。
    この方法では、もし最新バージョンのビューがすでに仕様と異なっていた場合、Visual Regressinoテストでその間違いに気づくことができない。

  • デザインに変更がある場合は正のビューのデータを更新する必要がある。

  • 正のビューは画像として用意する
    HTML&CSSのテキストファイルとして用意する方法もあるらしいが、テスト対象のページがJavaScriptを使用しているページなので今回は除外。静的ページならその方法でもよさそう。

  • 動的要素をどのようにあつかうか
    同じページを表示しているのにバナーやカルーセルがあると、それらを差分と誤検知してしまう問題がある。
    これらに対する対策は、
    1.visibilityをhiddenにする。
    2.バナーやカルーセルにダミーのデータを用意する。
    などが考えられる。今回は、テスト用のライブラリなどに従い、visibilityをhiddenにする方向で行く。

検討過程

案1.定期実行

  • メリット 開発スピードに影響を与えない。

  • デメリット PRが複数取り込まれていたとき、デグレの原因がわからなくなる。 (実際に開発していると、ビューに影響があるPRかどうかはすぐにわかると思う)

  • 動作イメージ 定期的にビューのデータをS3に保存する。 保存したテスト対象のビューと正のビューを比較する。

案2.PRオープン時

  • メリット デグレの原因がPRに含まれていることがわかる。

  • デメリット スクショを撮るのに時間がかかるため、PRマージのスピードが遅くなる。

  • 動作イメージ PRオープン時に全てのビューをartifactsに保存する。 保存したビューと正のビューを比較し、その結果でCIをsuccess/failさせる。

以上を考えた上で、 ・デザインの変更は日常的に多くない ・スクリーンショットを撮るのでテストにある程度時間がかかる(開発のスピード感が失われる) ことを懸念して定時に実行することにした。

参考リンク

techblog.lclco.com

blog.kazu69.net

tech.recruit-mp.co.jp