くりーむわーかー

プログラムとか。作ってて ・試しててハマった事など。誰かのお役に立てば幸いかと。 その他、いろいろエトセトラ。。。

CypressとJestのカバレッジをマージする

以前、Nuxtの単体テストをCypress使ってやる奴を書きましたが、実際にやってみてこれはこれでつらかった。

やっぱりメソッドとか簡単な部分はJestというかVue-test-util使ってちょこちょこっと書けた方が良い。

でもやっぱりあれこれやり始めるとVue-test-utilだとつらい・・・。

じゃー、使い分ければいいじゃんと。

で、そういう時に問題になるのが、カバレッジのマージ。

nycはいちをそれも出来るんだけど、マージの仕方が何か微妙な気がするのですが・・・。

どっちかにあるものの、MAXで見るか、平均で見るかって感じ?

単純に通ったコードのカウント部分マージしてくれればいいんだけどなー。

何でこういう感じになってるんだろ?何かやり方が間違ってるのかしら?

公式にも載ってるサンプルのリポジトリと同じやり方してみても、上手くいかない。

というか、ぶっちゃけ現状バグってますよね?istanble-lib-coverageがおかしいのかしら?色々やってみると大体結局↓のエラーが出る。

TypeError: Cannot read property 'start' of undefined

多分これ、coverage.jsonのファイルって下の感じの定義じゃないですか。

statementMap:{
 "0":{
     start:1,end:1
  },
 "1":{
     start:2,end:2
  }
},
s:{"0":3, "1", 4}

で、sのオブジェクトがstatementMapの定義してる行数を通った回数になってると思うのですが、

マージすると、statementMap側に存在しないキーがs側に出来る場合があるっぽ。

ダメじゃん。

同一ソースなら一緒になるはずなのですが、

jestとcypressで微妙に定義の仕方が違うん場合があるんですよね。行数は一緒なんですけど。


なので、cypressとjestの組み合わせ限定ですが、coverage.jsonをマージするスクリプトを作った。

別に大した事はやってないのですが、だいぶ面倒くさいところなので、何かに使えれば参考にどうぞ。

下記にあげました。

https://github.com/n79s/cy-jest-coverage-merge

10億人が笑うSVGからナゼか正規表現の話

Billion laughs攻撃っていうのがある。

XMLで参照を多重に定義して、メモリを食いつぶさせてPCとかアプリを固まらさせるやつ。

で、これってSVGでも可能だったんですね。

下の画像をFireFoxで見るとFireFoxのタブが固まる。(Chromeは大丈夫だった)

https://github.com/cirosantilli/web/blob/master/svg-billion-laughs.svg

上の画像をDLして、例えばパワーポイントとかに画像挿入しようとするとパワポも固まる。


上の画像のソースを見ればわかりますが、この程度の参照の組み方だけで、

組み合わせ爆発でヤバイ事になるという訳なんですが、

参照をネストさせるようなものはやっぱり考え物って事ですね。

正規表現なんかも、例えば

(a|b|c)(e|d|f)

みたいに組み合わせで色々やるとエライこっちゃになるパターンがあったと思う。

↑だけじゃ再現させられなかったんですが、昔どこかのコードで見たんだよなー。

組み合わせ爆発って怖いですね。結構意識せずにやっちゃいそうな気もする。


正規表現でいうとMSDNの正規表現のベストプラクティスのページがすごく面白かった。

長さが 5 文字を超えると、文字列の文字が 1 文字増えるたびに処理時間が約 2 倍に増加します。 つまり、有効に近い文字列の長さが 28 文字になると処理に 1 時間以上かかり、33 文字になるとほぼ 1 日かかることになります。

確かに正規表現作ってる時って、正しい文字列ばっかり考慮してるきらいがありますよね。

「*」とか「+」とかのネストとかもやばそう。

正規表現だと楽ーとか早いとかいう話は良く見聞きしますが、

やっぱり一概にそうも言えないですよね。

MariaDBのクエリログ

完全にメモ。ささっと確認したい時にいっつも忘れる。

SET GLOBAL general_log=1;
SET GLOBAL log_output='TABLE';
SELECT * FROM mysql.general_log\G

戻すときは0にセット。

FILEの場合は多分この辺り。

/var/log/mysql/mariadb.log

公式DOC

AWSにVMイメージをインポートしてインスタンス作る(WindowsServer 2003)

WindowsServer2003という古のOSがありまして、

そのVMイメージをAWSで動かせるのかというお試し。

結果から言うととりあえず動かせはした。


VMインポートの手順は大まかに下記の流れ。

1. VMをエクスポートしておく
2. S3にバケット用意(既存を使うならそれはそれで
3. IAMで作業用のユーザ作っておく
4. aws cliをインストールしてconfig
5. aws cliでロールとか作る
6. aws cliでS3にVMイメージをアップロード
7. aws cliでアップロードしたイメージをAMIに変換
8. AMIからインスタンスを起動

基本的に公式のココのページ通りやっていけば大丈夫。


1. VMをエクスポート

色々やり方あると思うのですが、基本的にこのページのやり方でやらないとだめ。

2. S3にバケット用意

これはS3のサービス開けば問題ないでしょう。

3. IAMで作業用のユーザ作っておく

既存のユーザでも問題ないですが、後続のaws cliでアクセスキーとシークレットアクセスキーを使うのでそれが分からない場合は作るしかないかなと。

色々面倒そうなので、adminグループのユーザ作ってやった。。。

4. aws cliをインストールてconfig

公式のインストールのページから。windowsでやるのでwindows用をDLしてインストール。v2でやる。

インストールできたら、コンフィグ。

aws configure

> AWS Access Key ID [None]: *******
> AWS Secret Access Key [None]: *******
> Default region name [None]: ap-northeast-1
> Default output format [None]: json

東京リージョンは ap-northeast-1
5. aws cliでロールとか作る

公式のドキュメント

  • trust-policy.jsonを作成
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": { "Service": "vmie.amazonaws.com" },
         "Action": "sts:AssumeRole",
         "Condition": {
            "StringEquals":{
               "sts:Externalid": "vmimport"
            }
         }
      }
   ]
}
  • JSON作ったら vmimport っていう名前で作成
aws iam create-role --role-name vmimport --assume-role-policy-document "file://C:\work\trust-policy.json"
  • role-policy.json を作る
{
    "Version":"2012-10-17",
    "Statement":[
       {
          "Effect": "Allow",
          "Action": [
             "s3:GetBucketLocation",
             "s3:GetObject",
             "s3:ListBucket" 
          ],
          "Resource": [
             "arn:aws:s3:::ines-wr-tempdata",
             "arn:aws:s3:::ines-wr-tempdata/*"
          ]
       },
       {
          "Effect": "Allow",
          "Action": [
             "s3:GetBucketLocation",
             "s3:GetObject",
             "s3:ListBucket",
             "s3:PutObject",
             "s3:GetBucketAcl"
          ],
          "Resource": [
             "arn:aws:s3:::ines-wr-tempdata",
             "arn:aws:s3:::ines-wr-tempdata/*"
          ]
       },
       {
          "Effect": "Allow",
          "Action": [
             "ec2:ModifySnapshotAttribute",
             "ec2:CopySnapshot",
             "ec2:RegisterImage",
             "ec2:Describe*"
          ],
          "Resource": "*"
       }
    ]
 }
  • JSON作ったら vmimport に反映
aws iam put-role-policy --role-name vmimport --policy-name vmimport --policy-document "file://C:\work\role-policy.json"

※ローカルのファイルパスはフルパスで作ったJSONファイルを指定。

6. aws cliでS3にVMイメージをアップロード

下記の感じ。

aws s3 cp "C:\work\hogehoge.disk1.vmdk" s3://work/vm

vmdkだけあればよいっぽいけどとりあえずエクスポートで作られたファイルは全部上げた。

7. aws cliでアップロードしたイメージをAMIに変換
  • containers.json ファイルを作る
[
  {
    "Description": "Disk01",
    "Format": "vmdk",
    "UserBucket": {
        "S3Bucket": "work",
        "S3Key": "vm/hogehoge.disk1.vmdk"
    }
  },
  {
    "Description": "Disk02",
    "Format": "vmdk",
    "UserBucket": {
        "S3Bucket": "work",
        "S3Key": "vm/hogehoge.disk2.vmdk"
    }
  },
  {
    "Description": "Disk03",
    "Format": "vmdk",
    "UserBucket": {
        "S3Bucket": "work",
        "S3Key": "vm/hogehoge.disk3.vmdk"
    }
  }
]

vmdk複数ある場合は↑の感じ。

  • インポートする
aws ec2 import-image --description "HogeTestVM" --disk-containers "file://C:\work\containers.json"
8. AMIからインスタンスを起動

インポートが終わったら、AMIにイメージが出来てるのでそれを選んで起動すればOK。


ここまでで、大体動くようにはなってると思う。

ただ、本当はここから下記の設定をした方がよいっぽい。

インスタンス上げてみてみると、EC2Configの方は勝手にインストールされてた。

ただ、ENAとNVMe のドライバーのインストールはWindowsServer2003では不可能っぽい。

何でかって言うとPowerShellが2.0しか入れられないから。

がんばれば3.0以降も入るのかな?どこかで2003は2.0しか動作しないような事を見た記憶ががが...

ENAとNVMeはあきらめましたとさ。

でも、とりあえず動いてはいる。

顧客向け用の環境としてはあり得ないんだけど、開発用でどうしても一時的に必要な状況はあるので、何かの参考に置いておきます。

windows server 2003をAWS上に復元するのとか検索しても全然出てこなかった。

まーやる人なんかいないですよね。。。

AWSのLinuxサーバをデスクトップ化してローカルのWindowsからRDPで接続

まとめ。AWS側はCentOS7。

# SELinux切る(とりあえず)
sudo setenforce 0
sudo vi /etc/selinux/config
  SELINUX=disabled

#ファイヤーウォール切る(とりあえず)
sudo systemctl stop firewalld
sudo systemctl disable firewalld

# デスクトップ環境
sudo yum groupinstall graphical-server-environment -y

# VNCサーバー
sudo yum install tigervnc-server -y

# EPELリポジトリを有効化
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -y

# xrdp
sudo yum install xrdp -y

# xrdpの起動とサービス化
sudo systemctl start xrdp
sudo systemctl enable xrdp

# パスワード変更(RDP接続時は必須っぽ)
sudo passwd centos

あとは、RDPのポート(3389)をIPフィルタで外してあげればローカルのリモートデスクトップでつなげる。

パスワード変更しても通常のSSHでの接続でパスワード求められるわけじゃない。

AWSのWindowsサーバを日本語化する

デフォでローカルが英語なので日本語化したい。

前は設定から日本語選べば自動的に言語パックDLして適用してくれたみたいなのですが、

最近はやってくれない模様。そのうち治るのかしら?


①インターネットオプションで信頼済みサイトに下記

https://*.microsoft.com

➁IEのURLに下記を入れて直DL


https://software-download.microsoft.com/download/pr/17763.1.180914-1434.rs5_release_SERVERLANGPACKDVD_OEM_MULTI.iso

➂上記をダブルクリックで「Microsoft-Windows-Server-Language-Pack_x64_ja-jp.cab」がある事を確認。

④Windowsキー + Rでファイルを指定して実行:langpacks

⑤で、上記のja-jp.cabを選択してインストール

⑥ウィンドウズキー⇒設定⇒言語

⑦言語でAddからjapaneseを追加

⑧あとはリージョンとか適当に設定。

20200716追記

⑨コンパネから行く地域も日本にしないとダメでした...


言語パックのDLってMicrosoftのページに無いのかしら。

見つけられなかったのですが...

NuxtのテストをCypressでCoverage付でやる

Nuxtのテストがつらい。vue-test-util使って書くのがツライ。

簡単なコンポーネントなら良いと思うのですが、ガチでテスト書こうとすると

mountとか色々上手く動かなかったり、都度アレコレ調べて、「苦肉の策」みたいなコードを

書かないといけないのがつらすぎる。

皆アレでやってるんですかね?書けなくはないんだけど、つらすぎじゃないですか?


という事で、CypressでE2E的に単体テストをやりたくなった話。

Cypressで単体テストをやろうとすると問題になるのが、カバレッジ。

カバレッジが取れないので無理だよなーとか思ってたら、ちゃんと出来るっぽいので組み込んでみた。

最終系は下記に上げてます。

https://github.com/n79s/nuxt-cypress-coverage-sample

参考


まず必要なパッケージのインストール。

npm install --save-dev @cypress/code-coverage nyc istanbul-lib-coverage babel-plugin-istanbul cypress

そしたら一回cypressを動かしてテンプレのファイルとか作ってもらう。

npx cypress open

あとは設定。

  • ./nuxt.config.js
  build: {
    babel: {
      plugins: [['babel-plugin-istanbul']],
    },
  },
  • ./.babelrc
{
  "env": {
    "test": {
      "plugins": ["istanbul"],
      "presets": [
        [
          "@babel/preset-env",
          {
            "targets": {
              "node": "current"
            }
          }
        ]
      ]
    }
  }
}
  • ./nyc.config.js
module.exports = {
  all: true,
  extension: ['.js', '.vue'],
  exclude: ['**/*.{spec,test}.{js,ts}'],
  include: [
    'pages/**/*.{vue,ts}',
    'layouts/**/*.{vue,ts}',
    'components/**/*.{vue,ts}',
    'module/**/*.js',
    'mixin/**/*.js',
    'store/**/*.js',
  ],
}
  • ./cypress/support/index.js
import './commands'
import '@cypress/code-coverage/support'
./cypress/plugins/index.js
module.exports = (on, config) => {
  require('@cypress/code-coverage/task')(on, config)
  on('file:preprocessor', require('@cypress/code-coverage/use-babelrc'))
  return config
}


あとおまけで、vscodeでcypressのインテリジェンス効くようにする。

  • ./jsconfig.json
{
  "include": ["./node_modules/cypress", "cypress/**/*.js"]
}


あとは適当にコンポーネントとか作って実行すると下記の感じでカバレッジが取れるようになる。

カバレッジはデフォだと「coverage/lcov-report/index.html」

sample-cov


どうやってカバレッジ取ってるのかと思ったら、

カバレッジ用のオブジェクト(パスが通ったら該当行のカウントアップするやつ)を

「window.__coverage__」に丸ごと登録してブラウザ側に渡して、ブラウザで実行される時に、

実行してる行のカウントアップをしてるっぽい。

なるほどなー。


で、これだとブラウザのUIを通してしか実行が出来ない。

例えば、Vuexの値を直で見たい場合とかComponentのmethods何かを直で動かしたい場合にどうするかというところ。

まずVuex。

Nuxtは自身をwindow.$nuxtに登録しているのでそれを下記の感じで取得すれば直で呼べる。

const getStore = () => cy.window().its('$nuxt.$store')

    getStore().its('state.vcounter').should('equal', 6)//値を直で見る
    getStore().then((store) => {
      store.dispatch('setCounter', 10)//アクション呼ぶ
      getStore().its('state.vcounter').should('equal', 10)
      cy.wrap(store.getters.vcounter).should('equal', 10)
    })

Componentは一工夫。というかかなり無茶が必要。

ブラウザ側からやる場合、どうしてもコンポーネントの参照をどこかに持たないと無理。

なので、コンポーネントがmountされる時に、自身をwindowに登録するようにpluginでグローバルミックスインを置いておく。

import Vue from 'vue'

if (window.Cypress) {
  window.$allComponents = []

  Vue.mixin({
    mounted() {
      if (this.$vnode) {
        if (String(this.$vnode.tag).includes('pages'))
          window.$allComponents.push(this)
      }
    },
  })
}

通常は入れたくないので、Cypressで動いてる時だけやるようにする。

全コンポーネントでやってもいいと思うのですが、自分はページコンポーネントだけでやってる。

ページコンポーネントの$childrenにそのほかのコンポーネントは入ってるのでそれでいいかなと。

そしたらこんな感じで使う。

const getPageComponent = (pagepath) =>
  cy
    .window()
    .its('$allComponents')
    .then((compos) => {
      for (const x of compos) {
        if (String(x.$vnode.tag).includes(pagepath)) {
          return x
        }
      }
    })

describe('Counter Test Component Direct', () => {
  it('ClickCounter', () => {
    cy.visit('http://localhost:3000')
    cy.get('.button--grey').click()
    cy.url().should('include', '/sample02')

    getPageComponent('pages/sample02').then((target) => {
      cy.wrap(target.$children).its(0).invoke('handleClick')//methods の関数を直呼び
      cy.wrap(target.$children).its(0).its('vcounter').should('equal', 2)//data()を直参照
      cy.wrap(target.$children).its(0).invoke('handleClick')
      cy.wrap(target.$children).its(0).invoke('handleClick')
      cy.wrap(target.$children).its(0).its('vcounter').should('equal', 6)
    })
  })
})


ただ、これだとVue側の警告が裏で上がってるので他に良いやり方無いかなー。

プログラミング言語 最近の流行り廃り 2020

前に見てたの思い出したので今年(もう去年か)はどうなったのか確認してみた。2020のアンケートもそろそろ出るんじゃないかと思うんだけど、まだ2019までしかなさそうですね。


2020/5/28

と思ってたら昨日出てた。見た目すごい気合入ってる。

https://insights.stackoverflow.com/survey/2020


Googleトレンド

sample

まだ、Pythonの方が検索されてるのね。どこかでhaskelみたいな関数型やんなきゃダメだろーみたいな事言ってる人見たのでhaskelどんなもんかと思ったのですが、結構全然アレなのかしら。

StackOverFlowのアンケート(2020)

https://insights.stackoverflow.com/survey/2020

言語でまとめ

pg-order

フレームワークでまとめ

fr-order

プログラミング言語

sample-pg

去年からJavaをPythonが抜かしたのね。

WebFramework

sample-fr

jQueryは根強いですね。一時代を築いただけの事はある。レガシー的に残ってるのか、全然まだ第一線なのか。Angularも叩かれてる印象が強いのですが、使われ具合だとまだまだ健在?

MostLovedを見るとReactとVueがほぼっぽいし、jQueryはレガシー扱いになってそう?そもそも考え方違うしケースバイケース的なやつ?とりあえずの流行りはReactとVueでしょうか。

好きなフレームワーク

sample-loved-fr

嫌いなフレームワーク

sample-dreaded-fr

Database

sample-db

MySQLがちょっと復活。やっぱり一強。DBランキングだとOracle強いんだけど何でなんでしょ。対象にしてる人達が違うのかな?

MariaDBは個人的に頑張ってほしい。

Platform

sample-pf

開発者さんたちの環境的にはLinuxとWindowsって均衡してるんですね。世の中的にはWindowsダントツだったと思うけど。

そういえば、dockerってどうなんでしょ。たしか日本のdocker本番利用って15%くらいで伸び悩んでましたよね。あと、docker自体もクラウド環境での基盤?事業は売却して、開発者向けに注力するみたいなのをどこかで読んだ気がする。dockerは開発者さんのローカル環境で生き残ってく感じになるのでしょうか?CentOS8なんかも標準でPodmanになったみたいですし。先行き不透明。


Pythonの勢いはまだまだ健在?やっぱWebはjavascript祭りですね。ReactよりVue好きなんだけどなー。どっちも良いのですが。何かVueの方が好き。そういえば、nuxtのcore-js3.0で動かない問題はどうなるんだろうか。core-jsのメンテナ不在らしいですね。OSSのリスキーな面が推されちゃってる感じ。

あと、アンケート結果のMostLovedにも載ってたけど、Rustが割と良さそうな感じがするので、ちょっと本腰入れて使ってみようかな。。。

AWS CentOS8の公式イメージ

コメントで教えていただきました。centosのwikiに載ってた。(20200704追記)

コメントありがとうございます。

今のところCentOS8の公式イメージはココに載っているAMIで提供してる模様。

東京リージョンなら↑のページのAMIのIDコピーして、AWSのAMIで検索して起動すれば、

とりえあず起動はいけました。

ami-01

ami-02

ami-03

動かしてみよ。。。

以下、当初に書いたもの。


まだ無いらしい。

CentOSのForum上でも微妙に話題になってはいる。

誰かやってくれ~みたいな感じ?

今のところ、MarcketPlaceに2つの会社が上げてくれてる。コミュニティ上にも何個かはある。

ただ、公式イメージはない。

現状、自分でやる場合は↓の「CentOS-8-ec2-8.1.1911-20200113.3.x86_64.qcow2」使って自分でAMI登録しなさいって事みたい。

https://cloud.centos.org/centos/8/x86_64/images/

コミュニティ上のやつは、上げた人が自分用に作ってる感じなので、不要なパッケージとかも入ってたりするので、ちょっと微妙?まー十分ありがたいのですが。

日本人的に「公式」って言葉に弱いので、そろそろ対応して貰えると嬉しいんだけどなー。

あと、Stream版ってどうなんでしょ。開発に貢献したい人用な感じがするので、手を出すのはちょっと躊躇する。。。

Nuxtの開発環境をDockerで

DockerでNuxtのローカルの開発環境作りたくなった。

やってみたのですが、なかなか思い通りにいかなかったので記載。

やりたい事としては、nodeとかnode_modulesとかはdocker側において、ソースはローカル。

で、ローカルのソースを修正したら、nuxtというかVueのホットリロードを動かしたい。

ひとまずソースの構成。

.
├── app
│   ├── Dockerfile
│   └── webapp # nuxtのアプリ
└── docker-compose.yml

nuxtのアプリを作る

cd app
npx create-nuxt-app webapp # 質問は適当に動けばとりあえず。。。

で、ここでは「npm install」はしない。やった場合は後述。

Dockerfile

FROM node:14.1.0-alpine

WORKDIR /app

# 多分、nuxt動かすだけなら、@vue/cliとか@vue/cli-initはいらないと思う。
RUN apk update && \
    npm install -g npm && \
    npm install -g @vue/cli && \
    npm install -g @vue/cli-init && \
    npm install -g create-nuxt-app

ENV HOST 0.0.0.0

CMD ["npm", "run", "dev"]

Docker-compse

version: '3'
services:
  webapp:
    build: ./app
    ports:
      - 13000:3000
    volumes:
      - ./app/webapp:/app
    tty: true

ホスト側のPortは適当に。tty:trueはあっても無くてもどっちでも。docker内のコンソール出力を全部見たいのでひとまず付ける。

そしたら「docker-compose build」

build終わったら下記でコンテナ内で「npm install」する。

docker-compose run webapp ash
npm install
exit

そしたら「docker-compose up」

これで、上記のポートの割り当てだったら「http://localhost:13000」でnuxtのデモ画面が出る。

そのまま、ローカルのファイルを修正すればDocker側にも反映されてホットリロードされると。

全ソースはここに上げてます


で、ここから出来なかった事。

本当はbuildのところもdockerfile側に置きたい。↓の感じ。

COPY ./webapp/package.json /app/package.json
COPY ./webapp/package-lock.json /app/package-lock.json
RUN npm install

↑は上手くいくのですが、nuxtの実行をすると、「.nuxt」ってディレクトリ作られるじゃないですか?

こいつがかなりやっかいで、実行時に動的に作ってるらしく、ローカルのディレクトリと共有してると権限がおかしくなって動かなくなるのです。

dockerignoreとかマウントしてからvolumeで部分的に上書きして~とかローカルのuidと合わせて~とか色々やってみたのですが、どうにも上手くいかない。

今のところ上手くいった方法が上述のnpm installはbuild後にupする前にコンテナ内で実行しておくという手順。

んーカッコ悪いんだけど、開発環境としてローカル側にソース置きたい場合はこれしかやりようがなさそう。


途中でnpm installとかnpm run devしちゃって「node_modules」「.nuxt」出来ちゃってる場合はコンテナ内に入る前に全部消す。

sudo rm -rf .nuxt
sudo rm -rf node_modules
問合せ