たいきゅんの日記

ITエンジニアの積み上げ日記

Redisに入門してみた。

今回は入門記事として、Redisの入門をアウトプットしてみます。
Redisを使った開発が最近初めてだったので、キャッチアップ記事としてまとめていきます。

Radisとは

RedisはRemote Directory Serverの略で、メモリ上でデータを管理するインメモリデータベースです。
メモリ上で動作するため高速で、システムが頻繁に読み出すデータの複製を高速に配信するキャッシュサーバーとして用いられることが多いです。NoSQL型のDBでkey-value型に分類されます。
C言語で開発されており、AWSではAmazonElasticCacheのエンジンにRedisが採用されています。
使用されているサービスとして、slackやPinterestが挙げられます。

インメモリデータベース

データを**メインメモリ上(RAM)**上の領域に格納するように設計されたDB・DBMSで、電源を切ると中身が失われてしまいます。
システムの終了・再起動時や一定時間ごとにメモリ上の内容をストレージに保存して、データの永続性を保持する機能が搭載されています。
ストレージ上に構築するDBに比べてデータの読み書きを**数桁高速に**行うことができる一方、大量のデータを保持するにはコストがかかってしまうのが特徴です。

特徴

1. データ永続化設定
インメモリデータベースのため、データはサーバーの電源を落とすと消えてしまいます。データ永続化のためRDBとAOF二種類の永続化方法があります。
RDBRedis Data Baseの略で、あるタイミングのスナップショットを残す機能です。
AOFはAppend Only Fileの略で、データが更新されるたびに更新履歴を記録していくトランザクションログ機能のことです。
両機能を同時に有効にすることが可能でこれが推奨されています。デフォルトではRDBのみ有効となっています。
AOFファイルとRDBファイルの両方が存在する場合は**AOFファイルが優先**されます。
RDBファイルはRedisの起動時に自動的に読み込まれ、前回終了時のデータが復元されます。


2. 複雑な形のデータを操作し保存できる
一般的なkey-valueデータベースとは違って複数のデータ型が用意されているため、多くのデータ型を扱うことが可能です。
(例: 文字列型・リスト型・ハッシュ型)

3. 不整合が生じない
Redisはトランザクション処理のように複数の操作を一連の流れで実行する際も、全**ての操作が正しく完了しない限り、データが最初の状態に戻る**特徴があります。よって複数の処理が**全て実行されるか、全く実行されないかが保証**されており、データの不整合が生じないです。

4. 各言語のクライアントで取得したデータを使用可能
JavaPythonPHPなどの各種言語で取得したデータが使用可能です。

5. メモリの消費が大きい
メモリ上で動くため、サーバーやPCのコスパが下がる可能性があります。

環境構築(Docker環境)

docker-compose.yml

version: '3'
services:
  redis:
    image: "redis:latest"
    ports:
      - "6379:6379"
    volumes:
      - "./data/redis:/data"
      # redisの設定ファイル
      - "./redis.conf:/etc/redis.conf"


redis.conf

# メモリの最大値を設定
maxmemory 100MB

# Redisのメモリ量がmaxmemoryに達した場合、LRCアルゴリズムに従いどれかのキーを削除
maxmemory-policy allkeys-lru

上記2ファイルを用意してもらい、docker-compose up -dでコンテナを立ち上げます。
その後コンテナに入り、redis-cliコマンドでシェルを起動させることで完了です。

まとめ

Redisの基礎と簡単な環境構築まで紹介しました。
概要は紹介できたと思うので、実際に触りながら学習を進めればRedisを使いこなせるようになるはずです。
最後まで読んで頂きありがとうございました。

minioに入門してみた。

今回は、開発環境でいつも動いているけど何者か分からなかったminio(ミニオ)について調べてみようと思います。



minioとは

分散オブジェクトストレージです。イメージとしてはS3に似たもので、オブジェクトストレージを構成するためのソフトウェアです。最大5TBまで保存できGo言語で実装されています。


特徴

1. S3の代わりをローカルで実現できる。

minioはS3互換のAPIが実装されているため、S3の開発をローカル環境で行う際に代わりにminioを使用することができます。つまり本番環境ではAmazon S3・開発時には、MinIOで開発・テストする。といった開発が可能です。




2. Dockerとの相性

Docker環境で動作確認することが可能でDockerとの相性がいいこともminioの特徴。




3. AWSの動きを確認できる

さらにaws-cliやコンソールから操作することが可能でaws-cliの動きの結果をminioで確認することができるのも特徴の一つです。




4. 分散構成を取れる

Minioは1台でも実行可能だが、分散構成も取れます。分散構成の場合、オブジェクトは自動的に分散・複製されて保存され、ストレージ破損に備えることができます。

一方で後からノードやストレージサイズを増やすことができない。つまり予め決まったサイズで運用をするか、新たなMinioクラスタを構築して、データの保管場所を調整するなどの対応が必要になります。



Docker環境サンプル

Docker環境でminioを動かすためのサンプルを紹介します。



docker-compose.yml

version: '3.9'

services:
  minio:
    image: quay.io/minio/minio:latest
    environment:
      MINIO_ROOT_USER: root
      MINIO_ROOT_PASSWORD: password
    command: server --console-address ":9001" /data
    ports:
      - 9000:9000
      - 9001:9001


この状態でbuild upしてもらいhttp://localhost:9001/ にアクセスします。
上記で設定したMINIO_ROOT_USER MINIO_ROOT_PASSWORDを入力することでログインができます。

AWS CLIの設定

(上記Docker環境でAWS CLIを使用することを想定)

xxxxxxxxxx minio-demo % aws configure
AWS Access Key ID [None]: root
AWS Secret Access Key [None]: password
Default region name [None]: 
Default output format [None]:

上記docker-compose.ymlで設定した値を設定することでAWS CLIを使用することができます。

バケット操作(aws-cli)

1. バケット作成

xxxxxxxxxxxx % aws --endpoint-url http://localhost:9000 s3 mb s3://miniotest
make_bucket: miniotest

(上記docker-compose環境で作成された環境前提)
上記コマンドで`miniotest`というバケットが作成されます。バケットはフォルダとは違って階層的にフォルダを掘っていくことはできないです。
コマンドのエンドポイントは9000番、ページのエンドポイントは9001番になるので注意。


2. バケット一覧

xxxxxxxxxxxx % aws --endpoint-url http://localhost:9000 s3 ls

2022-09-24 16:30:51 miniotest
2022-09-24 16:27:13 test-bucket


3. ファイルアップロード

xxxxxxxxxxxx  % aws --endpoint-url http://localhost:9000 s3 cp testfile s3://miniotest/testfile_from_local
upload: ./testfile to s3://miniotest/testfile_from_local

上記コマンドで、カレントディレクトリにあるtestfileを、miniotestバケットにtest_from_localという名前でアップロードすることができます。


4. ファイルダウンロード

xxxxxxxxxxxx  % aws --endpoint-url http://localhost:9000 s3 cp s3://miniotest/testfile_from_local testfile_from_s3
download: s3://miniotest/testfile_from_local to ./testfile_from_s3

上記コマンドで、miniotestバケットにあるtestfile_from_localを、カレントディレクトリにtestfile_from_s3としてダウンロードできます。

5. ファイルの削除

xxxxxxxxxxxx  % aws --endpoint-url http://localhost:9000 s3 rm s3://miniotest/testfile_from_local
delete: s3://miniotest/testfile_from_local

上記コマンドでminiotestバケットのtestfile_from_localを削除できます。


6. バケットの中身一覧表示

xxxxxxxxxxxx  % aws --endpoint-url http://localhost:9000 s3 ls s3://miniotest1                                                            
2022-09-24 17:02:30      69353 testXxx.png
2022-09-24 16:58:15     189249 test100.png

7. バケットの削除

xxxxxxxxxxxx  % aws --endpoint-url http://localhost:9000 s3 rb s3://miniotest
remove_bucket: miniotest

上記コマンドで、miniotestバケットを削除できます。

まとめ

実際に動作確認してみると、S3と相違ない開発体験を得ることができました。
開発環境でS3を使うことに抵抗がある方にとってminioは良い選択肢になると思いました。
最後まで読んで頂きありがとうございました。

Amazon DynamaDBに入門してみた。

今回はAmazon DynamaDBに関してまとめていこうと思います。

最近開発を任されたプロジェクトが、DynamaDBを使用しておりました。

開発するにあたり最低限の知識は抑えたいということで、アウトプットしていきたいと思います。

 

 

Amazon DynamaDBとは

DynamaDBは、AWSが開発したマネージドデータベースサービスの一つです。NoSQLに分類されます。

DynamaDBはAmazonのCTOによって開発されました。その背景はCAP定理という「一貫性」「可用性」「ネットワーク分断耐性」を全て達成することはできないという考えがあります。この中で可用性」「ネットワーク分断耐性」を重視して開発されたのがDynamaDBです。

AmazonECにおいて、”いつでもカートに追加できる=可用性”、”カートに入れたデータを失わない=ネットワーク分断耐性”を、大量に処理することができるDBを目的として開発されました。

 

DynamoDBの特徴

得意なこと

1. フルマネージドサービスのため、自動的に容量の拡張やレプリケーションが実施される。その他目運用負荷の軽減が可能。

 

2. key-value およびドキュメントデータモデルをサポートしている点

 

3.  一行ミリ秒単位のレイテンシーを要求するアプリケーションにも対応していおり、DBMSと異なり非常に高速に実施することが可能な点

 

4.高可用性

・データの保管時にはデフォルトでデータが暗号化がされる(追加料金不要)

・ポイントインタイムリカバリ (PITR) を使用することで、オペレーションによって DynamoDB テーブルが誤って上書きされたり削除されたりしないようにできる。

・オンデマンドバックアップおよび復元で、DynamoDB テーブルのデータの完全なバックアップを作成してアーカイブできる。

・3つのAZに保存するためデータの信頼性も高い

 

苦手なこと

1. データのジョインができない

2. トランザクション・コミット・ロールバックができない。

3. 柔軟な検索ができない

4. 集計処理ができない

 

向いているシステム

1. ミリ秒単位のアクセスレイテンシーが求められるシステム

2. RDBMSのような複雑なデータ構造は扱わないシステム

3. データの容量が予測しにくいシステム

 

(具体例)

・モバイルゲームにおけるデータ収集

・アカウント管理

・web広告におけるクリックストリーミング

・IOT機器の利用

 

DynamoDBの設計上の考慮点(キー設計)

DynamoDBはテーブルのデータをパーティションと呼ばれる領域に分けて保持します。つまりデータがどのパーティションに保存されるかはパーティションキーによって決定されます。またパーティションにデータを保存する際は、ソートキーで指定した順序によって保存されます。

このパーティションキー・ソートキーの設定がDynamoDBにおいて重要です。DynamoDBだとクエリが柔軟に発行できないので、設計段階から各種データにどのようにアクセスできるかをきちんと考えておく必要があります。データが多すぎるパーティションはクエリに時間がかかってしまう可能性が発生します。

 

ポイントインタイムリカバリ (PITR) 

DynamoDB テーブルを、偶発的な書き込みや削除のオペレーションから保護できる機能のこと。過去35日間の任意の時点にテーブルを復元することができます。直近の最も遅い復元日時は約5分前までの指定が可能。

既存のテーブルに書き戻しができるわけではなく、あくまでバックアップを復元し、データを確認することができるにとどまります。

 

キャパシティモード

キャパシティーユニットとは、事前に設定しておく読み込み/書き込み容量のこと。オンデマンドキャパシティープロビジョニング済みキャパシティーという 2 種類のキャパシティーモードがあり、これらの二つの料金体系が存在する。

 

1. オンデマンドキャパシティー

システムがAmazon DynamoDBに対してデータを読み書きした回数に対して料金が発生するプラン。アプリケーションのI/Oの予測がつかないもの向き。

 

2. プロビジョニング済みキャパシティ

システムがAmazon DynamoDBに対する1秒あたりのデータ読み書き回数を指定し、指定した回数を元に料金が算出されるプラン。Auto Scaling を使用すれば、指定した利用率に応じてテーブルのキャパシティーが自動的に調整されるので、アプリケーションのパフォーマンスを確保しつつコスト削減が可能。

 

料金体系

料金を決める要素は下記の3つになる。

 

1. キャパシティーユニット

2. ストレージ容量

3. データ転送量

 

まとめ

DynamoDBの説明は以上です。

個人的には最初のNoSQLでしたがかなり掴みやすく、直感的な操作が可能なサービスとなっておりました。Dockerにて公式イメージもあるので、ローカル環境でNoSQLを試すのもいいかもしれません。

ただし設計となると話は変わってくるため、導入のハードルは高いものとなっているなという印象です。

最後まで読んでいただきありがとうございました。

Terraformに入門してみた。

今回はTerraformに入門してみたと題して、Terraformとは何者か?ということをざっくり紹介できたらなと思っております。

最近知らない技術に業務で触れる機会が本当に多く、入門記事ばかりですがお付き合いください。

 

 

Terraformとは

TerraformはHashiCorpが開発しているIaCツールでGo言語で開発されています。

www.hashicorp.com

 

IaC(Infrastructure as Code)とはインフラをコード化して管理する方法で近年注目されており、こちらを実現するツールの一つとしてTerraformが存在します。競合ツールとして有名なのがAWS CloudfFormationです。

CloudfFormationとの大きな違いとして、「プロバイダーを問わない」点にあります。CloudfFormationはAWS専用のIaCツールですが、TerraformはAWSはもちろん、Azure・GCP等といったほとんど全てのプロバイダーに対応しています。

また独自のTerraformCLIが存在し簡単なコマンドでインフラを作成・削除することが可能です。

 

Terraformの仕組みと基本コマンド

terraformの仕組みを基本コマンドと一緒に紹介します。

 

1. terraform init

Terraformの環境を構築したら最初に実行する必要があるコマンドです。Terraformの初期設定を行なってくれるコマンドで、ワークスペースの初期化やプラグインがダウンロードされます

 

2. terraform plan

terraformの規則に従ってコードを書き終えた時に実行するコマンドです。変更内容が表示されるコマンドで、コードで記載した内容が正しいか確認することができます。

(例 S3バケットをap-north-eastで作成します。みたいな内容が表示される)

 

3. terraform apply

planで変更内容を確認したら、applyで変更を実行します。コマンドを実行すると変更内容が表示されるので、問題がなければyesを入力します。入力後リソースの構築が実行され、正常に終了すれば完了です。

 

4. terraform destroy

applyしたリソースを破棄するコマンドです。apply同様コマンドを実行すると破棄対象が表示されるため、問題なければyesを入力します。入力後リソースの破棄が実行され、正常に終了すればリソースが削除されます。

 

ここまでが流れになります。

流れとは別に一つ整形するコマンドを紹介します。

 

(番外編)terraform fmt

インデントなどのスタイルをフォーマットするコマンドです。gitにコミットする際等、整形したい時に実行するコマンドです。

 

tfファイル

terraformのコードを記載する際は拡張子.tfを用いたファイルを使用します。tfファイルの書き方が決まっているのでそのフォーマット(一例)を紹介します。

 

resource "リソースの種類" "リソース名" {

 設定項目1 = 値1

 設定項目2 = 値2

 設定項目3 = 値3

}

 

こちらはresourceを記述する際のフォーマットになります。ここでいうresourceは例えばAWSVPC・サブネット・EC2インスタンス等を指しています。

"リソースの種類"の箇所にVPCやサブネットといった値を設定(書き方は公式ドキュメントを参照)します。

"リソース名"は任意の名前を指定することが可能です。

 

上記はリソース指定の際の書き方ですが、プロバイダーを指定する際の書き方は別のフォーマットになります。しかしシンプルで分かりやすくそんなに難しく感じないのではないかと思います。

 

(例)

プロバイダーをAWSを指定。リージョンをap-northeast-1に指定する場合

 

provider "aws" {

 region = "ap-northeast-1"

}

 

その他記載方法は公式ドキュメントを参照してください。

 

tfstateファイル

Terraformではデフォルトでtfstateファイルというものが存在します。名前の通りTerraformで管理しているインフラの状態を記録するファイルです。tfstateファイルは自動生成され、保存場所を指定してしない場合Terraformを実行したディレクトリに保存されます。

インフラに変更を加える場合、Terraformはtfstateファイルを見てリソースの追加・変更があるかを判断しています。ローカルにtfstateファイルがあると、メンバーが最新のtfstateファイルからリソースの状況を参照できなくなるため、通常はS3などメンバーが共有できる所で管理します。

 

Terraform実行環境構築

terraformを実行するために必要なツールはterraformの環境とAWS CLIです。またTerraformを実行するためのAWSクレデンシャルが必要です。terraformの環境はDockerを使って作成することも可能です。

私はAWSクレデンシャルの準備とDockerで環境を構築し実行しています。

 

まとめ

入門編としてterraformの基礎をまとめてみました。

IaCツールの入門としてこれから入る方には、CloudFormationよりはterraformから入りプロバイダー問わずインフラを作成できる方がいいかもしれないです。

今後本格的にterraformを触っていくので実務で感じたことがあったらまた記事にしてまとめてみようと思います。

最後まで読んでいただきありがとうございましたmm

jestに入門してみた~Matcher編~

今回はjest入門~Matcher編~としてmatcher(マッチャー)についてまとめてみます!

環境構築 - 最初のテストまで編の続きとなりますので、環境構築はこちらを参考にしてみてください。(Vue3+Dockerで環境構築しております。)

 

URL...

 

 

Matcher(マッチャー)とは

マッチャーとは、「テストの評価条件を定義するメソッド」のことです。

マッチするかどうか?の確認をすることを確認するメソッド群と捉えて差し支えないと思います。

 

主なMatcher

toHaveBeenCalled

モック関数が呼ばれたかどうかを確認するマッチャー。

// マッチャー
test("モック用のマッチャー", () => {
const mockFunc = jest.fn().mockReturnValue(100);
mockFunc(1);
expect(mockFunc).toHaveBeenCalled();
 
});

 

toBe

等価であることを確認するマッチャー。

test('two plus two is four', () => {
expect(2 + 2).toBe(4);
})

 

toHaveBeenCalledTimes

モック関数が期待した回数だけ呼ばれたことを確認するマッチャー。

import fooBar from "@/fooBar";

test('部分モック', () => {
 
const spy = jest.spyOn(fooBar, 'foo').mockReturnValue('mock');
expect(spy).toHaveBeenCalledTimes(1);
})

 

toHaveBeenLastCalledWith

最後に呼び出された関数に渡された引数をチェックすることができるマッチャー。

第一引数 想定される値

test("モック用のマッチャー", () => {
const mockFunc = jest.fn().mockReturnValue(100);
// 2回呼出
mockFunc(1);
mockFunc(2);
 
expect(mockFunc).toHaveBeenLastCalledWith(2); // 最後の呼出の引数
});

 

toHaveReturned

モック関数が少なくとも1回正常に返された(エラーをスローしなかった)ことをテストできるマッチャー

// マッチャー
test("モック用のマッチャー", () => {
const mockFunc = jest.fn().mockReturnValue(100);
// 2回呼出
mockFunc(1);
mockFunc(2);
expect(mockFunc).toHaveReturned();
});

 

toHaveReturnedTimes

モック関数が指定した回数だけ正常に実行された(エラーをスローしなかった)ことをテストできるマッチャー。

第一引数 number

test("モック用のマッチャー", () => {
const mockFunc = jest.fn().mockReturnValue(100);
// 2回呼出
mockFunc(1);
mockFunc(2);
 
expect(mockFunc).toHaveReturnedTimes(2);
});

 

toHaveNthReturnedWith

モック関数がn回目に返した値が特定の値であるかどうかをテストするマッチャー。

// マッチャー
test("モック用のマッチャー", () => {
const mockFunc = jest.fn().mockReturnValue(100);
// 2回呼出
mockFunc(1);
mockFunc(2);
 
expect(mockFunc).toHaveNthReturnedWith(1, 100); // 1回目の戻り値
});

 

toHaveLastReturnedWith

モック関数が最後に返した値が特定の値であるかテストするマッチャー。

test("モック用のマッチャー", () => {
const mockFunc = jest.fn().mockReturnValue(100);
// 2回呼出
mockFunc(1);
mockFunc(2);
 
expect(mockFunc).toHaveLastReturnedWith(100);
});

 

toMatchSnapshot

スナップショットと一致することを確認するマッチャー

モックの全呼び出しの引数・戻り値が前回実行時から変わっていないことをテストする。

// マッチャー
test("モック用のマッチャー", () => {
const mockFunc = jest.fn().mockReturnValue(100);
// 2回呼出
mockFunc(1);
mockFunc(2);
expect(mockFunc).toMatchSnapshot();
});

 

toEqual toStrictEqual

オブジェクト・配列の等価チェックができる。両者の違いは、undefinedの扱い方。

toStrictEqualの方がより厳密に判定できる

test('expect.toEqual/toStrictEqual', () => {
expect({foo: 'var'}).toEqual({foo: 'var'});
expect({foo: 'var'}).toStrictEqual({foo: 'var'});
expect([1, 2, 3]).toEqual([1,2,3]);
expect([1,2,3]).toStrictEqual([1,2,3]);
})

 

toBeTruthy toBeFalsy

true falseの判定を行うマッチャー。文字列やオブジェクト型でも判定ができるのが特徴。

test('toBeTruthy/toBeFalsy', () => {
expect(true).toBeTruthy();
expect(false).toBeFalsy();

// 空文字以外Truthy
expect('foo').toBeTruthy();
// 空文字以外Truthy
expect(1).toBeTruthy();
// 配列はTruthy
expect([]).toBeTruthy();
// オブジェクトはTruthy
expect({}).toBeTruthy();
// undefines/nullはFalty
expect(undefined).toBeFalsy();
// 0はFalty
expect(0).toBeFalsy();
// 空文字はFalty
expect('').toBeFalsy();
});

undefined null

undefined nullの判定を行うマッチャー。判定は下記の通り。

test('toBeUndefined/toBeNull/toBeDfined', () => {
expect(undefined).toBeUndefined();
expect('foo').toBeDefined();
// nullはundefinedではない
expect(null).toBeDefined();

expect(null).toBeNull();
expect('foo').not.toBeNull();
// undefinedはnullではない
expect(undefined).not.toBeNull();
});

配列長・文字列長

toHaveLengthマッチャーを使用。

配列や文字列数の判定を行うマッチャー。配列の場合は要素数をカウントしてくれる。

test('toHaveLength', () => {
expect('foo').toHaveLength(3);
expect([1,2,3]).toHaveLength(3);
})

正規表現

toMatchマッチャーを使用する。

文字列を正規表現で判定するマッチャー。

test('toMatch', () => {
// 正規表現部分一致
expect('foo12345').toMatch(/foo\d{5}/)
// 正規表現全体一致
expect('foo12345').toMatch(/^foo\d{5}$/)
// 部分一致
expect('foo12345').toMatch("foo")
})

配列要素

toContain toContainEqualマッチャーを使用する。

配列要素がプリミティブ型はtoContainを使用し、配列要素がオブジェクト型の場合はtoContainEqualを使用する。

test('toContain/toContainEqual', () => {
// プリミティブ値
expect(['foo', 'bar']).toContain('foo');
// オブジェクト型
expect([{ foo: 'bar' }, {foo: 'hoge'}]).toContainEqual({ foo:'bar' })
});

 

例外処理

toThrowマッチャーを使用する。引数にはテスト対象のメソッドを関数でラップ。

引数を省略するとエラーが検出されたことのみチェックする。

引数には型・オブジェクト・messageの値を指定できる。

// エラーになることを検証
expect*1.toThrow();
// エラーの型判定
expect*2.toThrow(CustomerError);
// エラーオブジェクトの確認
expect*3.toThrow(new Error('エラー発生'));
// messageプロパティの確認
expect*4.toThrow('エラー発生');
// エラーメッセージの正規表現の確認
expect*5.toThrow(/^エラー.*$/);
})

 

参考

jestjs.io

 

今回はマッチャーについてまとめてみました。

これである程度簡単なテストは書けるようになったのではと思います!

最後まで読んでいただきありがとうございました。

*1:) => throwError(''

*2:) => throwError(''

*3:) => throwError('エラー発生'

*4:) => throwError('エラー発生'

*5:) => throwError('エラー発生'

Jestに入門してみた(環境構築 - 最初のテストまで)

こんにちは!

今回はJest入門についてアウトプットしていこうと思います。

会社の新規プロジェクトでNuxtを使用することとなり、Jestをテストフレームワークとして導入しているので、そのキャッチアップの記事になります。

 

Jestとは

公式ドキュメント

 

JestはJavaScriptのテスティングフレームワークの一つです。

JavaScriptフレームワーク(Vue React等)、やシンタックスシュガー(TypeScript)等javaScriptを使用したものは基本使えるものとなっています。

npmかyarnがあれば簡単に導入することが可能です。

特徴として一番はスナップショット機能なのではないかと思っています。フロントエンドのテスト初心者の私にとって、この機能は画期的でした。。

 

環境構築

今回は、Vue3+Docker環境にJestを導入する方法をご紹介します。

Dockerfile docker-compose.ymlの説明は割愛します。

 

バージョン情報

docker Version:           20.10.17 
docker-compose version 1.29.2

 

Dockerfile

FROM node:17-alpine3.14

WORKDIR /var/www/html

RUN apk update && \
npm install -g npm && \
npm install -g @vue/cli

EXPOSE 8080

 

docker-compose.yml

version: '3.8'

services:
vue:
build: ./docker/vue/
tty: true
volumes:
- ./vue:/var/www/html
- 8080:8080

 

tree

├── docker
│   └── vue
│       └── Dockerfile
├── vue
| (略)
|
├── docker-compose.yml

 

こちらの設定で実行すればコンテナが立ち上がるはずです。

docker-compose up -d

 

コンテナが立ち上がったら、Vueプロジェクトの作成をしていきます。

vue create .

 

今回はカレントディレクトリにソースを置きたいので上記コマンドを実行します。プロジェクト名を付けたい方は自由に命名してもらって構いません。

 

ここからプロジェクトを作成していく上でJest関連のものをかいつまんで説明します。

 

Manuallyを選択

? Please pick a preset: (Use arrow keys)
❯ Default ([Vue 3] babel, eslint) 
  Default ([Vue 2] babel, eslint) 
  Manually select features 

 

Unit Testingを選択

? Please pick a preset: Manually select features
? Check the features needed for your project: (Press <space> to select,  to t
oggle all, <i> to invert selection, and <enter> to proceed)
 ◉ Babel
 ◯ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◯ Router
 ◯ Vuex
 ◯ CSS Pre-processors
 ◉ Linter / Formatter
❯◉ Unit Testing
 ◯ E2E Testing

 

テストフレームワークの選択>Jestを選択

? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Linter, Unit
? Choose a version of Vue.js that you want to start the project with 3.x
? Pick a linter / formatter config: Basic
? Pick additional lint features: Lint on save
? Pick a unit testing solution: (Use arrow keys)
❯ Jest 
  Mocha + Chai 

In dedicated config filesを選択

? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Linter, Unit
? Choose a version of Vue.js that you want to start the project with 3.x
? Pick a linter / formatter config: Basic
? Pick additional lint features: Lint on save
? Pick a unit testing solution: Jest
? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
❯ In dedicated config files 
  In package.json 

 

この4点は注意して後はご自分の好みにカスタマイズして、プロジェクトを作成していください。

自動的にJestが入ったProjectが作成されると思います。

 

テストファイル

プロジェクト作成されるとtests/unitというディレクトリが自動生成されていると思います。この配下にテストを記述していきます。

tests/unit配下には予めexample.spec.jsというファイルが生成されており、サンプルが自動で用意されています。サンプルのようにテストファイルは.spec.js(あるいは.spec.ts)という拡張子を設定する必要があります。

 

テスト実行コマンド

今回はnpmを使用して環境を構築しているので下記コマンドで実行できます。

npm run test

上記コマンドをコンテナに入った状態で実行すればテストが実行されるはずです。

 

簡単なテストの実行

それでは簡単な足し算のテストを実行してみましょう。

test('one + one', () => {
expect(1 + 1).toBe(2);
});

 

上記を記載した後テストを実行してみてください。

中身は書いてある通りなのですが、こちらは「1+1の結果は2である」というテストです。

テストの実行にはtestメソッドあるいはitメソッドを使用します。

第一引数には、テストの概要の説明を記述し、第二引数に関数形式でテストを記述していきます。テストの概要はテスト実行時のログに出力されます。

今回のテストではexpectとtoBeを使用しております。意味の通り、expectで実行したい式等を記述し、toBeで予想される結果を記述します。今回はそれぞれ式と結果の数値を設定してみました。

このようにシンプルで分かりやすいのがJestのいい所です。

 

今回は以上になります。

次回以降もう少し深掘りしていこうと思います。

最後まで読んで頂きありがとうございました!!

Nuxt.js入門

こんにちは。

業務でNuxtを使用するので、その入門として調べたことをアウトプットしてみます。

入門として、フォルダ構成・パス・Vuexについて簡単にまとめてみます。

 

1. Nuxt.jsとは

Nuxt.jsはVue.jsのフレームワークのことです。Nuxt独自の概念もありますが基本的にはVue.jsの知識がそのまま使えるので、Vueができればそう参入障壁も高くないように思えます。

Nuxtのメリットをいくつか挙げると、以下のものがあります。

 

1. SSRができる

2. PWAモジュールが使用できる

3. head要素の取得が容易にできる

4. ルーティングを自動設定してくれる

5. TSとの互換性

 

他にもありますが、Vue.jsをさらに強化したもので非常にサクサクと開発できるフレームワークです。

 

2. Nuxtのフォルダー構成

Nuxtプロジェクトを作成すると自動で必要なフォルダ、ファイルを作成してくれます。その種類と中身は下記の通りです。

.git gitが使用するもの
.nuxt Nuxt.jsのアプリケーションが生成されている。デフォルトでは作成されず、npm run dev実行時に生成される
assets アプリケーションで使うスタイルシートJavaScriptファイルなどを配置
components コンポーネントファイルをまとめるフォルダ
layouts レイアウトファイルを配置するフォルダ
middleware ミドルウェアが配置されているフォルダ
node_modules プロジェクトで使用するパッケージ類がまとめられたフォルダ
pages 各ページ用のファイルをまとめるフォルダ
plugins プラグインのプログラムを配置するフォルダ
static イメージファイルなどを保管するフォルダ
store データを管理するためのファイルを用意するフォルダ
.editorconfig エディター設定情報
nuct_config.json Nuxt.jsの設定ファイル
package.json

パッケージ管理ファイル

 

この中でも最初はpages store assets staticフォルダをよく使用します。

 

3. デフォルトページの表示とパス

Nuxtプロジェクトを立ち上げると下記のように表示されるはずです。

Nuxtトップページ

こちらのページがどこから読み込まれるのかですが、こちらはpages/index.vueが元に表示されています。各ページのコンテンツはpagesフォルダーにまとめられており、ファイル名がそのままアドレスのパスになります。

例えば/a/a というアドレスのページを作成したいときは、pages/a/a.vueファイルを作成すれば、Nuxtがルーティングしてくれます。Vueの場合は、自身でルーターを設定する必要がありましたが、その必要がないのでNuxtは便利です。

そのためrouter-linkもタグを書くだけでaタグを作成できます。

 

(例)

<router-link to="/other">Go to other</router-link>

 

4. パラメーターの取得

ID等をGETで送信する場合にパラメーターをどのように取得するのかです。

例えば、http://〇〇/abc/パラメーターで値を送信したいときはpagesフォルダー内にabcというフォルダーを作成し、そこに_〇〇.vueという名前でファイルを用意します。xyzという名前でパラメータを受け取りたい場合は、_xyz.vueファイルを作成します。

パラメーターは$routeという変数のparamsプロパティ内にまとめられています。例えばxyzという名前でパラメータを送った場合は、下記で取り出すことができます。

 

this.$route.params.xyz

まとめると/id/passで値を取得したい時、/hanako/1 と送信するとid=hanako pass=1をthis.$route.paramsで取得することができる。

 

5. Vuex

nuxtにおけるVuexの利用方法は

 

1. storeフォルダにスクリプトを用意します。そしてstoreフォルダ内のスクリプトにより変数や必要な処理を用意します。

2. $storeを利用します。$storeにはVuexのオブジェクトが保管されており、この中から値などを取り出すことができます。

 

(例)

store/index.js

// Vuexという名前でオブジェクトを作成する
import Vuex from 'vuex';

const createStore = () => {
// Vuex.Storeというオブジェクトを作成する関数を定義。Vuex.StoreオブジェクトにVuexの情報をまとめて管理
return new Vuex.Store({
// state=Storeに保管する値を用意するために必要。componentのdataに似たもの。
state: function(){
return {
message: 'This is store message!',
};
},
})
}
// export 他のファイルでimportすることでcreateStore関数が使用できるようになる(特別な記述は不要)
export default createStore;

$storeの呼び出し(例ではmessageの中身を出力)

<p>{{$store.state.message}}</p>

 

5. mutation

コンポーネント側で$store.stateの値を直接書き換える操作は推奨されていない。そのため$store.stateの値操作を行いたいときは、ストア側で値の操作を行う。この操作にはミューテーションという機能を使う。

const createStore = () => {
    return new Vuex.Store({
        state: function(){
            return {
                message: 'This is store message!',
                counter: 0,
            };
        },
        mutations:{
            count(state) {
                                // カウントアップするmutation
                state.counter++;
            },
            reset(state) {
                                // リセットを実行するmitation
                state.counter = 0;
            }
        },
    })
}

 

ミューテーションの機能をコンポーネント側から呼び出すにはcommitメソッドを使用します。commitメソッドでは名前を指定する必要がある。

 

<div class="link" 
  v-on:click="$store.commit('count')"
 v-on:click.alt="$store.commit('reset')">
 <a>Clicked:{{$store.state.counter}}</a>
</div>

(例)

clickで$storeに設定されているmutationのcount関数を呼び出す。

click.altで$storeに設定されているmutationのreset関数を呼び出す。

 

ざっとですが以上になります。

axiosとか、CompositionAPI、その他Nuxtの機能は別記事にてまとめてみたいと思います!!

最後まで読んでいただきありがとうございました!!