雑ノート(仮)

適当なメモ。

「ソフトウェアテスト293の鉄則」を読んだ

テスト本2冊目。

ソフトウェアテスト293の鉄則

ソフトウェアテスト293の鉄則

著者はテスト業界の偉い人たちらしい。中には「知識ゼロから学ぶソフトウェアテスト」で見たことのある名前もあった。 本書は鉄則とあるが、テストにおける重要な規則を教科書的に網羅した本ではない。 見出しこそ「〜べし、〜せよ」というものが多いが、どちらかというとテーマごとに複数の著者が持ちあったエッセイ集という性格が強いと思う。

とにかく網羅しているテーマの範囲が広く、自動化やドキュメントはもちろん、キャリアや転職やマネジメント、テスターの評価なども扱っている。 日頃からテストに関して疑問に思っていることや違和感などがあれば本書のどこかでハッとさせられる記述が見つかるかもしれない。

初心者が読む本というより、ある程度経験がありながらもテストという作業にうまく言語化できない違和感を抱えている人が読むのが良いと思う。

新しく知ったこと

  • テストの5大要素

    • テストの実施者
    • 網羅性
    • 発見したい問題
    • 作業内容
    • 結果の判定方法
  • テストの自動化は難しい

    • 戦略・計画がまともでないと失敗する
      • テストの目的を理解、説明できない人に自動化を行わせてはいけない
    • 同じテストケースを実施するなら人間がやる方が価値がある。
      • コンピューターはテストケース以外のことを問題意識を持って観察はしない
        • 異音がする、極端な性能劣化が発生する、画面がちらつくなど

考え直したこと

  • カバレッジ
    • 100%でも足りない
      • 実装されていないことによるバグの発見が漏れる*1
      • テストの漏れは数字からはわからない
    • 昔数万行の仕様が不明のレガシーコードをカバレッジを取りながらテストしたことがある。
      • バグが発生する・しないテストデータ両方でメソッドごとにカバレッジを計測し、差分が出た箇所を精読してバグを見つけた
      • あの時はちょっと感動した
      • バグを探す糸口としてカバレッジはかなり有効だと思う。
  • IEEE 829 (ドキュメント)
    • ドキュメントを管理できるスケジュール、プロセスになっていない場合、採用すべきでない
    • 膨大な資料の作成は考える力を奪い問題意識を持って取り組むことを妨げる

*1:意外とある^^;

オーム社の電子書籍サービスが終わるらしい

estore.ohmsha.co.jp

情報系の学部を出ていたら、この出版社から出た教科書の1、2冊は持っているのではないでしょうか?*1

最近だとt_wadaさんの新訳のテスト駆動開発なんかもここから出ていました。

倒産とかではないですが、電子書籍ファンとしては悲しい一心です。

中身の一部は達人出版会で継続して販売されるそうです。*2

DRMフリーなので、撤退後も普通にコンテンツを読めますが、DRMかかってるサービスで撤退するということになったら色々大変でしょうね。

*1:今見たら情報系に限らず工学系全般を扱っているらしい

*2:移管というより昔から双方で売っていたらしい

macOS SierraにEclipseを入れる

インストーラを起動して見たところ警告が表示された。

Java SE 6 ランタイムをインストールする必要があります。

と出たのでAppleのサイトからJavaをインストール

ダウンロード - Java for OS X 2015-001

レガシー用Javaを入れ、再度インストーラを動かすと

Version:1.8 or greater is required.

と表示された。

いじめか?(笑)

とりあえずOracleのサイトからjava9をダウンロード

Java SE Development Kit 9 - Downloads

$ java -version
java version "9.0.1"
Java(TM) SE Runtime Environment (build 9.0.1+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)

インストーラーが動き無事ダウンロードができました(めんどくさ)

JavaScriptパターン第4章ノート

JavaScriptパターン ―優れたアプリケーションのための作法

JavaScriptパターン ―優れたアプリケーションのための作法

4章のテーマは関数です。

関数の記述方法

関数式

Var add = function add(a,b){
    return a + b;
};

Addを削除して無名関数にすることも可能。

関数宣言

function foo(){
    //処理内容
}

関数式と関数宣言の違いについて

  • 式は使用される前に記述されている必要がある、
  • 宣言は使用箇所の後に書いても問題ない(呼び出すことができる)
  • 宣言はグローバル空間か別の関数の中にしか存在できない。
  • 式で宣言したものは関数の引数で指定したり、戻り値として返すこともできる。
//- 式は使用される前に記述されている必要がある、
let num =  add(1,2)
Add = function(a,b){return a+ b};

//宣言は使用箇所の後に書いても問題ない(呼び出すことができる)
num = add2(1,2)
function add2(a,b){return a+b}

巻き上げ時の動作の違い

関数式は変数に代入しているので巻き上げが起こった場合エラーになってしまう 関数宣言の場合は新たに宣言した方で呼び出される

function test1(){
  console.log("test1");
}
function test2(){
  console.log("test2");
}

function hoisting(){
  console.log(typeof test1);//function
  console.log(typeof test2);//undefined
  test1();//hoisting test1
  test2();//Uncaught TypeError: test2 is not a function

  function test1(){
    console.log("hoisting test1");
  } 
  var test2 = function(){
    console.log("hoisting test2");
  }
  
}

ちなみに関数式の末尾にはセミコロンを必ずつけるべき(つけなくても補間されるけどね)

APIパターン

コールバック

関数を引数として別の関数に渡すことをコールバックという 渡すときには丸括弧()をつけない。(つけると呼び出した時点でも実行されちゃう…)

手頃なサンプルとしてArray.prototype.map()がある。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

var test = [1,2,3].map(function(a){
    return a *a;
});

//ES2015 allow function ver
var test = [1,2,3].map((a) =>{
    return a *a;
});

余談ですが、1年ほど前にpythonを勉強している時にmapとreduceというのは使いまくった覚えがあります。

またまた余談ですが、ネットを眺めると、関数は常に()付きで扱う、的な勘違いをして無駄に実行してしまうサンプルなどが散見される。qiitaなら優しい人がその丸カッコは不要ですよ〜って指摘してくれるけど

カリー化

Wikipediaの例はわかりやすかったが、本書の例は結構難しい。

本書の例

function schofinkelize(fn){
  var slice = Array.prototype.slice,
    stored_args = slice.call(arguments,1);
  return function(){
    var new_args = slice.call(arguments),
      args = stored_args.concat(new_args);
    return fn.apply(null,args);
  }
}

//nomal function
function add(x,y){
  return x + y;
}

// currying
var newadd = schofinkelize(add,5);
newadd(4);//9

Wikipedia

function div(x, y) { return x / y; }
//div(1, 3) == 1 / 3, これはカリー化ではない。

function cdiv(x) { return function(y) { return div(x, y); } }
console.log(cdiv(10)(3));
//=> 10/3 = 3.333...

var inv = cdiv(1);
console.log(inv(2));
//=> 1/2 = 0.5

引数の一部を部分的に適応した関数を新たに作る、程度の認識。 callbackを使うとこんなこともできるよ、という例で出したため今回はあまり掘り下げず、 Javascript関数型プログラミングを学ぶ素敵な本を見つけたのでそこでみっちりやる予定。

JavaScriptパターン第3章ノート

JavaScriptパターン ―優れたアプリケーションのための作法

JavaScriptパターン ―優れたアプリケーションのための作法

コンストラクタよりリテラルの方が良い・・・が一貫したこの章のテーマです。

オブジェクトリテラル記法

キーと値の組みをカンマで区切り、波括弧で囲う記法でオブジェクトを定義できる。

数値、文字、関数、正規表現、配列、別のオブジェクト を含めることができる。

コンストラクタを使う方法は冗長なのでオブジェクトの宣言はなるべくオブジェクトリテラルで行うべき

var obj1 = {
  sample_string:"normal val",// string literal
  sample_number:5, //number literal
  sample_function:function(){
    console.log("this is test function");
  }, //function literal
  sample_regexp:/normal/gi, //regure expression literal
  sample_array:[1,1,9], // array literal
  obj2:{
    sample_string:"this is nested object"
  }
}

//実験
console.log(obj1.sample_number + 15);//20
console.log(obj1.sample_regexp.test(obj1.sample_string));//true
console.log(obj1.sample_array.find((num)=> {return num > 8}));//9
console.log(obj1.obj2.sample_string);//this is nested object
var val1= obj1.sample_function;
val1();//this is test function
console.log(obj1);//{sample_string: "normal val", sample_number: 5, sample_regexp: /normal/gi, sample_array: Array(3), sample_function: ƒ, …}

カスタムコンストラクタ関数

Javascriptにはクラスがないので、クラスをインスタンスするためのコンストラクタ、というより、Objectを作成する関数という扱いなのか?そこがちょっとよくわからなかった。

var Person = function (name) { this.name = name;    
  this.say = function () {
  return "I am " + this.name; };
};
val John = new Person("john");
John.say();// I am John

コンストラクタにnewをつけ忘れると

コンストラクタは只の関数なので、newをつけずとも呼べてしまうが、その場合コンストラクタ内部でのthisはグローバルオブジェクト(window)を指してしまう

//※上記のPersonカスタムコンストラクタ関数を流用しています
var ken = Person("ken");
ken.say();//Uncaught TypeError: Cannot read property 'say' of undefined

console.log(ken)//undefined
window.say();//I am ken
say();//I am ken

初期化中のオブジェクトにプロパティを追加していると思いきや、グローバル変数を作ってるという事態になりかねない。対策としては

  • strictモード
  • コンストラクタ内で別のオブジェクトリテラルを返す
  • コンストラクタ内でthisを使わない
  • thisの型を検査し、適切に自オブジェクトをnew付きで呼び出す(自己呼び出しコンストラクタ)

のどれかが対策としては推奨される

配列リテラル記法

配列も組み込みコンストラクタではなくリテラルを使うべき。理由は数値型を単発で与えた時の挙動が特殊なため

var arr1 = new Array(3); //空の、長さ3の配列を作成
var arr2 = [3];//要素が 3 一つの配列を作成

arr1//[empty x 3]
arr2//[3]

var arr3 = new Array(3.14);//長さに小数点は採用できない・・・(エラー)
//Uncaught RangeError: Invalid array length

JSON

JSONでは関数や正規表現リテラルは使えないが、配列と文字だけを扱うならオブジェクトリテラルとして解釈可能。

JSONってweb apiとかで帰ってくる値でよく見る気がするが、そのままオブジェクトリテラルとして解釈できるのに驚いた。

例:WEB APIから住所を取得

geoapi.heartrails.com

最寄駅を取得可能なハートレイルズ様のAPIを利用しました。郵便番号はGoogle日本法人のオフィス(〒106-6126)にしました。

http://geoapi.heartrails.com/api/json?method=getStations&postal=1066126

{"response":{"station":[{"name":"\u516d\u672c\u6728","kana":"\u308d\u3063\u307d\u3093\u304e","line":"\u6771\u4eac\u30e1\u30c8\u30ed\u65e5\u6bd4\u8c37\u7dda","y":35.662799,"x":139.731151,"postal":"1060032","prev":"\u795e\u8c37\u753a","next":"\u5e83\u5c3e","prefecture":"\u6771\u4eac\u90fd","distance":328.0940048843225}]}}

こちらの取得結果をevalでjavascriptで評価して見ます*1

var nearestStation = eval({"response":{"station":[{"name":"\u516d\u672c\u6728","kana":"\u308d\u3063\u307d\u3093\u304e","line":"\u6771\u4eac\u30e1\u30c8\u30ed\u65e5\u6bd4\u8c37\u7dda","y":35.662799,"x":139.731151,"postal":"1060032","prev":"\u795e\u8c37\u753a","next":"\u5e83\u5c3e","prefecture":"\u6771\u4eac\u90fd","distance":328.0940048843225}]}});

nearestStation.response.station[0].name;//六本木
nearestStation.response.station[0].line;//東京メトロ日比谷線

ただしJSONではオブジェクトリテラルでは表現可能な関数、正規表現リテラルは記載できません。

あとevalを使ってJSONをパースするのはアンチパターンなのでJSON.stringifyを利用する

正規表現リテラル

リテラルを使う場合はコンストラクタで必要なエスケープが一部不要。簡潔性のため積極的にリテラルを使うべき。

ただし正規表現リテラルのオブジェクトは構文解析時にしか作られないため、実行時に組み立てるようなものはリテラルではなくコンストラクタを使うべき。

*1:evalは引数の文字列ををjavascriptとして解釈して実行しようとする関数です

JavaScriptパターン第2章ノート

JavaScriptパターン ―優れたアプリケーションのための作法

JavaScriptパターン ―優れたアプリケーションのための作法

4章まで読めたが、アウトプットが捗らない。5章は写経しないと俺の脳みそにはきつい。

補足:即時関数について

本記事では即時関数を利用しています。ピンとこない方は別記事に書いたものを読んでから本記事を読んでみてください。

Javascriptの変数スコープ

関数ごとにスコープを持つか、グローバル変数化のどちらかであるが、プログラミングの鉄則としてグローバル変数は極力使わないほうがいいという前提に立てば、意図せずグローバル変数を作ってしまう事象は極力避けるべきである。

暗黙のグローバルを避けよ

Varを使わない変数宣言は避けるべき。グローバルスコープを意図せず汚染する恐れがあるため

(function(){
  test = "hello" //暗黙のグローバル変数
  console.log(test)
}());

console.log(test); //hello

コード二行目のtestの宣言のvarを略さず影ば以下のようなエラーが出る。

ReferenceError: Can't find variable: test

代入の連鎖は禁止。片方がグローバル変数になる

(function(){
  var b=a="test"
  console.log("a is " + a+ " in function");//test
  console.log("b is " + b+ " in function");//test
}());

console.log("a is " + a+ " outside function");//test
console.log("b is " + b+ " outside function");//エラー(スコープ外)

暗黙的、明示的なグローバル変数の違い

暗黙の変数はdelete演算子で削除できるが 明示的に宣言したグローバル変数は削除でない

暗黙のグローバル変数は変数ではなく グローバルオブジェクトのプロパティとなるため。 変数は削除できないがプロパティは削除できる

var globalVal ="global";

(function(){
   implicitVal = "implict global";
   
}());

//どちらもglobalスコープ
console.log(globalVal);
console.log(implicitVal);

delete globalVal;
delete implicitVal;

console.log(globalVal);//global
console.log(implicitVal);//ReferenceError: Can't find variable: implicitVal

変数の巻き上げ

実に恐ろしい恐ろしい。 一般的に変数は利用箇所の近くで宣言するのが定石だが ES6以前の環境では明示的に関数の先頭に変数を宣言するのが望ましい。let,constの場合はreference errorになるが、巻き上げは起こっているらしい。

var val1 = "test"
console.log(val1); //test
(function(){
  //↓変数の巻き上げ!!!!!↓
  console.log(val1);//undifind
    

  var val1 = "testtest";
  console.log(val1);
}());
console.log(val1)

単独varパターン

ちょっと気持ち悪いが巻き上げによるバグを喰らわないためには致し方ない

(function test(){
  var a=1,b=2,c=3;
  console.log(a+b+c);
}());

eval()はワル

eval関数は引数の文字列をjavascriptのコードとして解析して実行しようとする。 eval("alert('eval is evil!!!!')"); 本書ではJSONのパースにevalを使ってはいけない、という例が出てきた。*1

XSSなどのセキュリティーリスクがあるので注意。

コードの中で eval() が使われているのを見つけたら、「eval() はワル」という呪文を唱えましょう。

余談ですが、この部分はeval() is Evilの有名なダジャレだけど、訳したり説明したりする気が一切ないのがちょっと切ない。

波括弧の位置

細かいイディオムの話は個人の嗜好でしかないと思うし、統一さえ取れて入ればなんでもいいと思うけど、波括弧の前に改行を入れるのはやめた方がいいと思った

function func() {
  return 
    {name: "Batman" };
}
var test  = fund();
console.log(typeof test);//undefined

上記の例だと二行目returnのあとにundifindが補完されreturn undifindとなり、続くオブジェクトリテラルは無視される。

一般的な命名ルール

コンストラクタは大文字始まりのキャメルケース 変数、関数は小文字始まりのキャメルケース

ただし変数にアンダースコアを含めたり、アンダースコアから始めることで変数の意味を補完するノウハウが紹介されていた

ドキュメンテーションについて

JSDoc Toolkitというjavadocのようなものがあり、そちらを利用できる。 多分Eclipseのようにメソッドの上で/**と入力し改行すると、ドキュメントのテンプレートが入るようなプラグインが各エディタにあるはず。昔salesforceのapex開発をしていた時にsublime textに似たようなアドオンを入れた覚えがある。

*1:JSONがオブジェクトリテラルだったという驚くべき話は次回へ続く

JavaScriptパターン第1章ノート

JavaScriptパターン ―優れたアプリケーションのための作法

JavaScriptパターン ―優れたアプリケーションのための作法

Javascriptはオブジェクト思考の言語である

ネィティブオブジェクト 言語側が用意 Arrayなど

Hostオブジェクト:ホストや環境が用意 Windodwなど

が、クラスという概念はない

Prototype

継承などの再利用の鍵となる

Prptopypeはオブジェクトであり、あらゆる関数はprototypeプロパティを持つ

ES5

ES3が99、ES4がポシャったため出版時の最新バージョンとなる

本書執筆時点で搭載ブラウザがないとかいてあるが、こんにちではつぎのバージョンであるES6がまともなブラウザには全て搭載れているという点にフロントエンドの変化の速さを感じる

Strict modeはes5から導入らしい。勝手に6からだと思っていた

JSLintの紹介

JavaScriptインタプリタ言語のため静的な構文解析が存在しない JSLintという静的解析ツールを使い、実行前に構文エラーなどはチェックすべき