まとめ 動作確認したのは v1.3.3 database/sqlのテストはgo-sqlmockを使うと比較的楽に行える クエリのmatcherには正規表現が使える Rowsからエラーを受け取りたい場合は、エラーが発生する行のデータを作る必要がある 不要なエラーのチェックだけならsqlmock.ExpectationsWereMetは呼び出さなくてもよい まえがき golangでSQLを使うコードを書く場合、database/sql を使うことになるが、golangの標準ライブラリだけでこれのテストを書くことは非常に辛い。 おそらくDBを実際に用意してテストするしか無いが、様々なエラーケースのテストが必要な場合それだけではテストしきれない。 この記事ではDATADOG/go-sqlmockを使ってテストした際のTipsをまとめておく。
はじめに 基礎的な部分はREADME.mdやexamples、godocを読めば事足りるが、以下に忘れがちな内容を記載する。
Query matcher クエリが実行されたかどうかをチェックするにあたって、呼び出された回数だけをチェックしたいケースが有る。 このような場合は、正規表現を使うことで対処できる。
mock.ExpectQuery(".*").WillReturnRows(rows) 雑だがgomockのAny()相当のことがしたい場合はこれで実現可能である。 また、QueryMatcher自体を自分でカスタマイズすることも可能だがこちらは試していない。
refs: https://godoc.org/github.com/DATA-DOG/go-sqlmock#QueryMatcher
Rowsからエラーを受け取る クエリの結果エラーを受け取りたい場合、 ExpectedQuery.WillReturnRows にエラーを含む sqlmock.Rows を登録することになるが、このとき以下のようにしてしまうとエラーが発生せずにハマることになる。
sqlmock.NewRows([]string{"ID"}).RowError(0, commonErr) パッと見は最初の行でエラーが出そうであるが、これではエラーは出ない。 多分この辺のせい。 以下のようにエラーが発生する行数になるまでAddRowを実行する必要がある。
sqlmock.NewRows([]string{"ID"}).AddRow(1).RowError(0, commonErr) 不要な呼び出しのチェック READMEのサンプルではmock.ExpectationsWereMet を実行してmockが呼び出されているか検証しているが、 SQLが実行されなかったことを保証するだけであれば このメソッドを呼び出さずとも良い。 例えばvalidationの結果、SQLが実行されないようなケースのテストでそのようなテストが必要になる。
ExpectXXX系のメソッドが呼ばれなかった場合に db.QueryContext のようなメソッドを実行すると、sqlmockがエラーを返すためそれを検証すれば良い。
github actionsを使ってgithub pagesをデプロイしていると、デプロイのたびにカスタムドメインの設定が消えてしまっていたため原因を調べた。
まとめ カスタムドメインを使用する場合はリポジトリルートの CNAME ファイルに指定したいドメインを記載する必要がある Hugoでは static/CNAME を作成すれば良い 起きていたこと github pagesでカスタムドメインを使用する場合、 settings タブからカスタムドメインの設定を行うが、これは公開中のブランチ( master もしくは gh-page)の CNAME ファイルを作成、更新する形で設定される。 このため、Hugoなどで生成したコードをそれらのブランチに対してデプロイするような構成にしていた場合は、生成されたコードに CNAME ファイルが含まれていないとデプロイのたびにカスタムドメインの設定が無効になってしまう。
refs: https://help.github.com/en/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site#configuring-a-subdomain
Hugoでの解決策 static/CNAME に指定したいドメインを記載する。
refs: https://gohugo.io/hosting-and-deployment/hosting-on-github/#use-a-custom-domain
Hugoには標準でGoogle Analyticsを組み込む機能があるため、以下の手順で設定すればOK
まとめ config.toml に googleAnalytics としてトラッキングIDを設定 テンプレート内に以下のどちらかの手段でトラッキング用のコードを埋め込む 既存のどちらかのテンプレートを使用する _internal/google_analytics.html _internal/google_analytics_async.html .Site.GoogleAnalytics という変数を使って自力で設定する トラッキングIDの設定 config.tomlに以下の内容を追記する
googleAnalytics = "UA-155249985-1" トラッキング用のJSの設定 使用しているテーマによっては既に登録されている可能性があるため、 googleAnalytics を設定したらまず一度サイトの挙動を確認する。 既にanalytics用のコードが埋め込まれてアクセスが発生しているようなら以降の作業は不要。
テンプレートに以下のどちらかのテンプレートを追加する。
{{ template "_internal/google_analytics.html" . }} {{ template "_internal/google_analytics_async.html" . }} .Site.GoogleAnalytics という変数がconfig.tomlに設定されたトラッキングIDを持っているため、これを使って自力でコードを書いても良い。
このactionを使えば難しいことはない。 getting-startedに書いてあることをそのまま実施すればOK。 今のこのサイトでは master ブランチを公開する設定にしているため、 source ブランチに生成元のコードを作成し、それらをもとにHugoで生成したファイルを master ブランチに展開している。 そのための設定は以下のようになる。
トリガーとなるブランチの変更 on: push: branches: - - master + - source jobs: build-deploy: デプロイ先のブランチの変更 uses: peaceiris/actions-gh-pages@v2 env: ACTIONS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }} - PUBLISH_BRANCH: gh-pages + PUBLISH_BRANCH: master PUBLISH_DIR: ./public 通常のgitの運用フローとかなり異なるため、 気に入らないようであれば外部レポジトリへのデプロイ機能を使ってページの生成元コード群と、公開ページのレポジトリを分けてしまっても良いだろう。
前回の記事の内容ではコンテンツにダブルクォーテーションなどのエスケープが必要な文字が入った場合にJSONとして不適切なレスポンスになるため修正する。
解決策 item.json.json を以下のように修正する
{{- dict "title" .Title "date" .Date "draft" .Draft "content" .Content | jsonify -}} 問題点 元々のitem.json.jsonでは、元データを変換せずにそのままレンダリングしてしまっていることが原因のため、何らかのエスケープを行えば解決する。
今回は以下のページを参考に、dictを作成してjsonifyで変換することにした。
https://gohugo.io/functions/jsonify/#readout https://knooto.info/hugo-snippets/#json%E5%87%BA%E5%8A%9B https://blog.8-p.info/ja/2018/05/26/hugo-json/
やりたいこと Hugoでブログを始めたものの、JSONでコンテンツをみることができると嬉しいので方法を調べてみた。
ビルドに使用しているのはMac上のHugo(Hugo Static Site Generator v0.62.0/extended darwin/amd64)
参考URL https://forestry.io/blog/build-a-json-api-with-hugo/
やったこと config.tomlにoutput formatを追加 以下の内容を追加。HTMLのページ自体はそのまま残したいのでHTMLとJSONを指定する。
[outputs] home = ["HTML", "JSON"] section = ["HTML", "JSON"] page = ["HTML", "JSON"] テンプレートを作成 layouts/_default 配下に以下のファイルを作成する。
ファイル名は {pageKind}.{outputFormatName}.{extension} という形式になる。今回は outputFormatName=json、 extension=jsonとなるので、JSON形式の出力の共通部分を記述した baseof、リスト表示用の list、単体表示用の single、それらの中で表示する1要素を表すための itemの4つを作成する。
baseof.json.json item.json.json single.json.json list.json.json layouts/_default/baseof.json.json { "data" : {{ block "response" .}}{{ end }} } このブログのJSONレスポンスは全てdata プロパティとして response ブロックをレンダリングして返す。 各 pageKindでは responseを定義する。
layouts/_default/item.json.json { "title": "{{ .Title }}", "date": "{{ .
ブログを放置しっぱなしだったので作り直してみる。
とりあえず手っ取り早くできる hugo + Github Page で作り直した。