「ソフトウェアテスト自動化の教科書」の感想

全体的な雰囲気として、(Web系のIT)エンジニアというより製造や品質管理といった言葉のイメージに近い領域を対象にしていると感じた。 テストの対象としてもWebブラウザ自動化といったものも含まれるだろうが、組込みシステムにも触れられていた(大変そう)。

組み合わせの数を減らす手法のオールペア法は初めて知った。全ての組み合わせでは膨大になるから、2つの組み合わせのみをテストするというもので、この本ではざっと説明しただけなので理解できなかったが、調べて理解してなるほどと思った。

自動テストとは不具合を減らすのではなく、レグレッションテストの工数削減のためというのを明確に述べていた(つまり、ファジングとかモンキーテストはこの本では対象にしていないということだろう)。 ユニットテストとかE2Eテストも結局はデグレ確認のためなので、再確認した感じがした(関係ないが、文字で書くまでレグレッション、リグレッション(regression)とデグレ(degradeに由来)を混同していた)。

自動テストの効果があるテストは、多くの回数を行うもので、改修により壊れることが少ないものという、限定的なものというのは書いてあり、やはり現実は厳しい (ユニットテストはドキュメント代わりになるというような副次的な効果もあるにはあるが)。

自動テストのツールの種類として、完全ノーコードでできるものよりスクリプトを使えるもののほうがいいということだった。 その理由は、ノーコードではぱっと見は便利で使いやすそうに見えるが、使ってみると柔軟性やできることが少ない。 一方で、スクリプトはやってみれば(非エンジニアでも)意外と難しくないということだった。

ちょっと意外ではあるが、(抽象度が高いスクリプト系の)プログラミング言語というのは、ぱっと見のとっつきにくさを除けば、多くの人が理解できるのであろう。 非エンジニアでも、ExcelVBA、WebデザインのCSS、Unityのスクリプト、マイクラのコマンドまでそれっぽいのに触る機会はあるものだ。

全体としては、やはりテストの自動化は一筋縄ではいかないので、よく考えて、振り返りもしつつやることが大事なんだなあという感想です。

TypeScriptのnoUncheckedIndexedAccessとそれに関連して欲しいかもしれない型

TypeScriptのnoUncheckedIndexedAccessと、それに関連して欲しいかもしれない型を書きます。

noUncheckedIndexedAccess について

まずtsconfigのnoUncheckedIndexedAccessを有効にすると、インデックスアクセスの返り値の型にundefinedが含まれるようになります。

const arr: number[] = [1, 2, 3];
const e = arr[0];  // この型は number | undefined になる

配列の境界外(またはsparse array(疎な配列)のemptyの要素)にアクセスするとundefinedが返るためです。

実際に有効にしてみると型にundefinedが含まれることによりかなりの数のエラーが発生して、直すのも大変です。

オプションを導入するissueでも、まともな開発者体験を得るにはTypeScriptに新たなControl Flow Analysis (CFA) を追加しないといけなくて大変と書いてありました。

Suggestion: option to include undefined in index signatures · Issue #13778 · microsoft/TypeScript · GitHub

実際にエラーが出たところを見ると、確かに要素数が0個のときを考慮していなかったかもというところがあって、実際に有効な場面もありそうでした。 (実装時の注意や、ユニットテストで見つけるべきなのかもしれないですが)

「n個以上の要素が含まれる配列」型

一応以下のようにTypeScriptで「n個以上の要素が含まれる配列」というのを表現する方法はあるようなので、noUncheckedIndexedAccessで出たエラーの一部はそれを使って解決できました。

TypeScript array with minimum length - Stack Overflow

type arrMin1Str = [string, ...string[]]; // The minimum is 1 string.

しかし、mapした後には普通の配列型になってしまう(mapで要素数は変わらないはず)、型を書くのが少し面倒、リテラルから自動で推論されないといった点はあるため、TypeScript組み込みでサポートしたほうが便利そうです。

配列の長さと関連付いた数値型

Array.lengthプロパティの返り値は単なる数値型なので、よくあるforループで配列の要素にアクセスするパターンでundefinedが含まれてしまいます。

const arr: number[] = [1, 2, 3];
for (let i = 0; i < arr.length; i++) {
  const e = arr[i];  // number | undefined
}

lengthの返り値の型を元の配列の長さと紐付けられればなんとかなるかもしれません。

他の言語では配列のアクセスはどうなのか

C#Javaは言うまでもなく、OCamlHaskellなどの静的型付けの関数型言語でも配列の範囲外アクセスは基本的に例外で表現します。

もちろん関数型言語のユーザは型にうるさい人が多いので、例外を投げる代わりに型で失敗を表現する方法も用意されているようです。(配列というかリストですが、OCamlではList.nthの代わりにList.nth_opt、Haskellでは!!演算子の代わりにlensライブラリを使うなど)

ただ、関数型言語の場合はループを使うことはそこまで多くなくて、map, filter, foldlなどでリストを処理することが多いように思います。

余談

調べていてこんな記事を見つけました。

exactOptionalPropertyTypes によせて - Object.create(null)

プロパティが減る方向の暗黙のキャストとオプショナルプロパティが組み合わさると、静的な型とは異なる実行時の型のデータが入ることがあるということです。

部分型を許さない型があるといいんですかね。

TypeScript をより安全に使うために まとめ - Object.create(null)

このあたりも知らなかったので参考になりました。 オブジェクトをMapとして使うのを避けるのと、積極的にreadonlyを付けていこうと思います。

スプレッド構文を後ろで使うと静的に見えないプロパティで上書きされるなど、静的に見れそうなところもありました。

余談 整数型を考える

TypeScriptのnumberはJavaScriptの数値型に対応するので、浮動小数点数を表します。 整数のみを表す型は標準では存在しません。

TypeScriptの型定義から、このフィールドは整数のみが入るのか、小数も入るのかがわからないので、別途コードや資料を確認したくなることがありました。

整数型があるとその情報を表現できるし、小数が来ないことで実装時に考えることが減るかもしれません。

感想

noUncheckedIndexedAccessの個人的な感想としては、なんかいい感じの型で検証できるようにして、いわゆるnull安全くらいには自然に使えるようになったらいいなと思います。 型検査の処理がかなり複雑化するかもしれないですが。

本の感想 ハイパフォーマンスWebサイト

会社にあったので読んでみた。

読み始めた後に気づいたが、もう15年くらい前の本で、だいぶ内容が古くなっていた。

JavaScriptのmangling(本では難読化と呼んでいる)をするとコードが壊れる危険があるのでやめたほうがいいとかいうことが書いてあり、牧歌的なWebの時代の名残を感じた。 IEがメインのブラウザであり、独自仕様も色々ある時代だったようだ。

とはいえ、通信の終了待ちがボトルネックになるとかはたぶん現在でもよくあるので、Chrome DevToolsでもNetwork waterfallが画面の大きいサイズを占めているのだろう。

また、Cache-ControlやEtagヘッダは現在でも使われているようなので、基本として知っておくべきと思った。(Etagははじめて聞いた)

SQLのサブクエリのユニークキー、Nullabilityを計算する

SQLのサブクエリのユニークキーの計算と、Nullabilityを計算するという2つの機能を持つプログラム。 動作の仕組みのメモはreadmeに書いた。

github.com

ちゃんと使えるようにすれば、バグの早期発見に多少は役立つのかもしれない。

このようなツールがすでにあったら知りたい。

ユニークキー

SQLWHERE foo = (SELECT ... )のように単一のレコードを返す必要がある箇所で複数のレコードが返ると実行時エラーになる。

SQLServerでは以下のメッセージ

メッセージ 512、レベル 16、状態 1、行 1
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

もちろん TOP 1 などでレコード数を最大1つにすればいいが、静的に検証したい。 ということで、試しにクエリのユニークキーを計算するプログラムを書いてみた。

スキーマはコード中に直書きしているし、対応している構文はごく一部になっている。

なんとなく動いた。

実際に使えるようになるには、where条件で主キーの絞り込みに対応したり、 サブクエリが式として使われる構文に対応する必要がありそう。

便利なのでIDEの機能につけばいいと思うが、なぜか見たことがない。自分が知らないだけかもしれない。 (フルのSQLに対応しようと難しいのだろうか。あるいは大して便利ではないのだろうか)

nullability

SQLの型検査でnullabilityを検査するやつを見たことないので簡単なものを作ってみた。

カラム自体のnullabilityはテーブル定義を見ればわかる。

外部結合によって結合先のテーブルのカラムがnullableになることがあるので、その検査をする。

SQLのNULLについて

C#などの言語でよくあるのは、オブジェクト型の変数の中身がnullになって、メソッド呼び出しでNullReferenceExceptionになるパターンである。

SQLの場合は、演算子オペランドがnullになると結果もnullになるし、関数の引数にnullが渡ると結果がnullになることが多い。 つまり、C#でいうNull-conditional operator .? のような動作がデフォルトになる。 意図せずにnullableになって問題になることもあれば、Null-conditional operator的な動作が便利で意図的に使うこともあるので、実際にnullableの検査を実装するとなると、ユーザへの表示の仕方が問題になりそう。

Excelのコマンド名を指定して実行 Command Palette

これはSpreadsheets/Excel Advent Calendar 2020 - Adventarの7日目の記事です。

こんな感じでコマンド名から操作を実行できるアドインを作りました。 (実際に作ったのはだいぶ前ですが)

f:id:kamocyc:20201207211055g:plain

機能

  • Ctrl + Shift + Pで、コマンド名を指定するコマンドパレットのダイアログを表示。
  • コマンド名を入力することで、部分一致するコマンドを絞り込み。
  • 絞り込み結果が複数ある場合、上下矢印キーでコマンドを選択。
  • Enterキーで選択したコマンドを実行。

Excelの標準コマンド名(英語)から検索して、コマンドを実行できます。

また、RelaxTools Addinのコマンド(日本語の説明あり)も同様に実行できます。

software.opensquare.net

ただし、とりあえず動けばいいという感じで作ったので、色々と雑なところはあります。

インストール方法

アドインファイル: https://github.com/kamocyc/excel-spreadsheet-example/raw/master/command_palette.xlam

  1. 上記のリンクからファイルをダウンロード
  2. C:\Users\<ユーザ名>\AppData\Roaming\Microsoft\AddInsフォルダに, ダウンロードしたファイルを置く。
  3. Excelを開き、「開発」 > 「Excelアドイン」 で、ダウンロードしたアドインを選択して有効化する。
  4. RelaxTools Addinをインストールする。

背景

以前ExcelVisual Studio Code (VSCode) をともに使っていたとき、ExcelでCommand Paletteの機能がないことが不便に感じました。

VSCodeのCommand Paletteとは、コマンド名をキーボードで入力することで、一致するコマンドを実行できるというものです。

f:id:kamocyc:20201207205307p:plain

すべてキーボードで操作が完結することや、GUIのメニューから欲しいものを探す手間がなくなるというメリットがあります。

特に、RelaxTools Addinは多くのコマンドがあるので、探すのが大変そうだと思い、作成しました。(すでに似た機能があったらすみません。。)

仕組み

アドインにコマンド名の一覧のシートを持たせていて、そこからコマンド名を検索しています。

Excel組み込みのコマンド名 (idMso というらしい) の一覧は、確かこことかから取得したような気がします。 (長いコマンド名完全一致とかでググると他のExcelのバージョンでのコマンド一覧も出ると思います。

コマンドの実行には、Application.CommandBars.ExecuteMso()を使っています。 (RelaxTools Addin内のコードを利用しています)

現状の問題点や改善したい点

たぶん、対応することは無いと思いますが。。

  • 色々と作りが雑。
  • 使用したコマンドの履歴を表示したい。
  • VSCodeのように、正確に部分一致しなくても文字列距離が近いコマンドを表示したい。

Excelの新機能LAMBDA: VBA無しで関数を定義する

この記事はSpreadsheets/Excel Advent Calendar 2020の6日目の記事です。 (遅れてすみません。。もう1本の記事も近いうちに書きます。。)

予定を変更してExcelのすごい新機能が発表されていたので紹介します。

insider.office.com

上記の記事でLAMBDAという新しい関数が発表されました。 これは、Excelの数式を使って関数を定義できるという機能です*1

今までの関数の作成方法の問題点

今までExcelでは、ユーザが関数を定義するためにはVBAJavaScriptといったプログラミング言語を使うしかありませんでした。 しかし、これには以下のような問題点があります。

  • VBAはローカルのファイルアクセス等も自由に可能なため、セキュリティの問題がある。
  • ユーザがVBA等のプログラミング言語を覚える必要がある。

一方、Excelの数式ではこのような問題はありませんが、VBAのように関数を定義できないため、 複雑な数式であってもコピペ(またはオートフィル)して使わざるを得ませんでした。

みなさんも複雑な数式をデータの各行にコピペして、数式を修正したらまたコピペして、、ということをやった経験があるかもしれません。 しかし、これも以下のような問題点があります。

  • 数式を修正した場合、コピー漏れの危険性がある(VBAなら関数のコードを直せば良い)。
  • 数式が複雑になると、書いた本人以外が理解できなくなる(VBAなら関数に名前を付けたり、コメント書いて理解しやすくできる)。

新しい関数LAMBDAを使うと、Excelの数式を用いて再利用可能な関数を定義できるため、これらの問題点を解決できます

新関数LAMBDA

構文は以下のとおりです。

=LAMBDA([parameter1, parameter2, …,] calculation)

calculationに関数の本体となる数式を記述し、そこで使う引数を[parameter1, parameter2, …,]に必要な数だけ書きます。

例えば、1を足す関数は以下のように定義できます。

=LAMBDA(x, x + 1)

定義した関数の本体はx + 1、その引数はxです。

Excelの「名前の管理」のダイアログを使ってこの関数に名前をつけてみます。

f:id:kamocyc:20201207123417p:plain

「ADD_ONE」という名前をつけてみます。ここでコメントも保存できます。

f:id:kamocyc:20201207123543p:plain

すると、ワークシート上のセルで

=ADD_ONE(2)

のように利用することができます。 この書き方は通常のExcelの関数やVBAで定義した関数と同じですね。

この場合、定義した関数の本体において、x2が代入されて2 + 1の計算が行われ、計算結果3が返ります。

関数に名前をつけずに利用

実は定義した関数に名前をつけずに利用することもできます。

セルに

=LAMBDA(x, x + 1)(2)

と入力してみます(LAMBDA( ... ) の部分は先程のADD_ONEと同じです)。

この場合、LAMBDA(x, x + 1)の部分で定義した関数に、引数2が適用されて、3が返ります。

実際、LAMBDA(x, x + 1)の部分をADD_ONEに置き換えると、=ADD_ONE(2)という先程と全く同じ式になることを考えると理解しやすいかもしれません。

いつ使えるの?

LAMBDAはOffice Insiderの以下のバージョンで使えるということです。

  • Windows: Beta Channel Version 2012 Build 13519.20000 以上
  • Mac: Beta Channel Version 16.45 Build 1201.0 以上

ただし、アップデートのタイミングはユーザによって違うので、人によってはもう少しかかるかもしれません。 (私は記事執筆時点はまだ使えないようでした)

もう少し深入り

こちらの記事により詳しい説明もありました。

techcommunity.microsoft.com

再帰

実はLAMBDAでは、定義した関数の再帰的な呼び出しができます。 (これにより、循環参照に頼らなくても、Excelの数式がチューリング完全になります。)

実務上は何が嬉しいかというと、可変長のデータに対する処理など、ループ処理を必要とする関数が書ける点があります。

参照元の記事に載っていた以下の例では、A列の文字列から、B列の文字をすべて取り除いて、C列の文字列を返すような関数を定義することを考えます。

f:id:kamocyc:20201207130559p:plain

SUBSTITUTE関数によって、「A列の文字列中から、B列の1番目の文字を空白に置換」、「その結果の文字列から、B列の2番目の文字を空白に置換」... と行えばよいですが、B列のデータは可変長なので、ループ処理が必要になります。

この処理を行う関数REPLACECHARSを以下のように定義できます。

=LAMBDA(textString, illegalChars,
     IF(illegalChars="", textstring,
       REPLACECHARS( 
       SUBSTITUTE(textString, LEFT(illegalChars, 1), ""), 
       RIGHT(illegalChars, LEN(illegalChars)-1)
)))

REPLACECHARSの定義の中の3行目に、REPLACECHARS自身の呼び出しが含まれています。

どういう計算過程になるのか少し分かりづらいですが、textStringにA列のデータ、illegalCharsにB列のデータを代入した状態から始めて、再帰呼び出しごとのtextStringとillegalCharsの変化を順々に追っていくとわかると思います。

例えば、"Excel2003"から数字を取り除く例だと、次のようになります。

f:id:kamocyc:20201207134923p:plain

illegalCharsが再帰のたびに1文字ずつ減っていき、再帰の最後ではillegalCharsが空になるので再帰呼び出しが停止して、すべてのillegalCharsの文字が除外されたtextStringが返ります。

これによって、B列の文字を1文字目から順番に取り出して、A列の文字列から取り除く(空白に置換する)という処理が実現できます。

※追記: 再帰の制限

アップデートが来たので実際に試してみたところ、再帰呼び出しの深さの上限が511回になっているようです (それより深く再帰呼び出しをすると#NUM!エラーになります)。

末尾再帰最適化*2も行われないようです。

もちろん、これらの制限は今後変更される可能性があると思います。

試しに (今話題になっている) n番目の素数判定のナイーブなコードを書いてみましたが、68番目が限界でした。

nth_prime_naive.txt · GitHub

扱えるのは数値や文字列だけではない

LAMBDAで定義する関数で引数として取れるデータは、数値や文字列はもちろんですが、動的配列やカスタムデータ型なども使うことができます。 これらの値を返すこともできます。

なお、LAMBDAで定義した関数自体も引数や戻り値として扱えます関数型言語のような first-class function)。実際、LAMBDAの導入に伴い、関数データ型が新たに導入されたそうです。

今後

LAMBDA関数に関して、すでに多くの改良が計画されているということです。 例えば、「名前の管理」ダイアログでの関数定義のUIは改善の余地があると認めています。

また、配列の操作関数をこの先数ヶ月で追加することで、動的配列の利点をより活かしてLAMBDAで関数が定義できるようにしていくということです。

また、Excelの数式にLETやLAMBDAのような関数型言語のような機能が追加される一方で、開発やデバッグのための機能は主流のプログラミング言語に比べるとまだ貧弱と言わざるを得ないでしょう。

Microsoftの人も、数式の編集やデバッグのための必要とされるツールを追加できたらいいなということを書いているので、近いうちに改善されることを期待したいです。

*1:知っている人向けに書くと、これはラムダ式そのものです。

*2:関数型言語でよく行われる関数末尾の再帰呼び出しをループに変換する最適化

PowerPointやWordで数式を入力するときのリンク集

研究に関するスライドを作るときに以前はbeamerを使っていたが、PowerPointのほうが圧倒的に効率が良い。

PowerPointでの一番の問題が数式の入力である。 やはり外部プログラムを組み合わせるなどしてLaTeXを使ったほうがきれいに表示できるが、かなりの部分はPowerPointのみでもできる。

基本的にリボンUIは使う必要は無く、ほとんどの操作はキーボードのみでできる。

例えば、数式モードで\sqrt(a/b)(最後にスペースを入力) とすると、\sqrt{\frac{a}{b}}と入力される。

PowerPointのみで数式を入力する際の参考リンクを書く。

環境:

  • Windows 10
  • Office 365 (2020年9月時点)

マニュアル

50ページあるが、ここに数式入力のほぼすべてが書いてある。全部読まなくても数式入力は使えるが、暇だったら読んでみると良さそう。

https://www.unicode.org/notes/tn28/UTN28-PlainTextMath-v3.1.pdf

コンパクトにまとめた資料

チートシート。便利。 いくつかバグの情報も載っていた。

https://www.cs.bgu.ac.il/~khitron/Equation%20Editor.pdf

数式の挿入のショートカットキー

記号の入力方法がわからないとき

なお、Office標準搭載の「インク数式」でも手書きで数式を入力できるが、あまり出てくる記号の種類が多くないようだ。

LaTeXとOfficeでの入力方法の違い

LaTeXとOfficeの数式の書き方比較 - Qiita

メモ