ぱと隊長日誌

ブログ運用もエンジニアとしての生き方も模索中

JSTQB AL テストマネージャ 受験記録 (2021/08/21)

始めに

2021/08/21 に「JSTQB認定テスト技術者資格 Advanced Level<テストマネージャ>試験」を受験してきました。試験中止となった回も含めれば、今回が3回目の挑戦となります。

1回目:JSTQB AL テストマネージャ 受験記録 (2019/8/24) - ぱと隊長日誌
2回目:JSTQB 第10回 AL テストマネージャ 勉強記録振り返り(2020年8月) - ぱと隊長日誌

今回の挑戦に向けて、どのような準備を行ったかまとめます。

また、前回までの受験記録と重複する内容は省いています。よろしければ前回まで(上記)の記事も参照ください。

略記について

本エントリ内では以下の略記を用います。教材の略記は個別に定義しました。

略記 名称
AL Advanced Level
TM テストマネージャ
TA テストアナリスト

教材と利用方法

【TM過去問セミナー推薦図書】

TM過去問セミナーでお勧めされていた3冊の本です。

現在はいずれも絶版となっており、古本で入手するのが現実的です。

今回は以下の順で読み進めました。

  1. ソフトウェアテスト12の必勝プロセス
  2. 基本から学ぶテストプロセス管理
  3. 体系的ソフトウェアテスト入門

ただ、各書が参照し合っている関係もあり、以下の順で読んだ方が良かったかもしれません。

  1. 基本から学ぶテストプロセス管理
  2. 体系的ソフトウェアテスト入門
  3. ソフトウェアテスト12の必勝プロセス

また、試験に直結した内容とは言い難いです。試験に合格するためではなく、テストマネージャとしての基礎力を身に着けるため学ぶというモチベーションで臨む必要があります。

シラバス

Advanced Level シラバス 日本語版 テストマネージャ

JSTQB認定テスト技術者資格-シラバス(学習事項)・用語集-

略記:TMシラバス

過去の受験勉強で読んではいましたが、今回も問題集を解くのと並行して何度か読み直しました。

スクエアリング・サービス TMシラバス解説書

スクエアリングサービス

略記:TMシラバス解説書

スクエアリング・サービスの有料コース(イータコース)を利用しているとダウンロードできます。

シラバスを引用しつつ、分かり辛いところを解説してくれています。

最新版のシラバスが Version2012.J04 に対し、当時のTMシラバス解説書は Version2012.J03 を参照していたこともあり、途中からはTMシラバスを優先して読み込むようにしました。

TMシラバス解説書の 2021/08/23 版からはシラバスの Version2012.J04 に対応しました。

【問題集】

スクエアリング・サービス テスティング中級コース(マネージャ編)

スクエアリングサービス

略記:スクエアTM問題集

テストマネージャ試験向けの日本語版の模擬試験サービスです。

解説が分かり辛い箇所を運営に連絡すると、後日解説が補充されるなど、丁寧な対応をしてくださいます。

スマホでも取り組みやすいので、通勤途中に繰り返し解きました。

アクセスが増えると動作が不安定になるようで、試験直前には利用できませんでした。

JSTQB Advanced Level テストマネージャ非認定問題集

略記:TM非認定問題集

JSTQB Advanced Level 試験勉強会」の発行する同人誌です。テストマネージャ試験に向けて作成した模擬問題80問が収録されています。

以前は BOOTH で購入できましたが、現在は購入できなくなっています。今後、無償公開を検討しているとのことです。

この勉強会を終了するにあたり、これまで頒布してきた同人誌は、順次無償公開を行うことを検討しております。また、無償公開の前には一定期間の頒布停止期間を設けることを検討しております。

<中略>

無償公開に向けたスケジュールは以下の予定です。

  • 2021年8月 : TM試験実施後、TM問題集の有償頒布終了
  • 2021年末 : TA問題集以外の有償頒布終了
  • 2022年2月 : TA問題集の有償頒布終了、勉強会の開催終了、TM問題集の無償公開開始
  • 2022年2月〜3月末 : 全問題集の無償公開開始、勉強会の活動完全終了
JSTQB® Advanced Level 試験対策勉強会 | 神奈川県川崎市を拠点に隔週で有志が集まり JSTQB® Advanced Level 試験の模擬問題を作って解く勉強会を開催しています。

ちなみに、BOOTH での販売ショップ名は「JSTQB Advanced Level 非公式問題集」(JSTQB Advanced Level 非公式問題集 - BOOTH)となっていますが、問題集のタイトルには "非認定" とあるため、今回の記事ではこちらの表記を採用しました。

JSTQB による Advanced Level 過去出題問題の解説セミナー資料

JSTQB認定テスト技術者資格-イベント-

略記:TM過去問セミナー

過去に出題された問題の一部を使って、試験内容の解説を行うセミナーが開催されていました。その際に用いられた資料です。

Advanced Level サンプル問題 日本語版 テストマネージャ

JSTQB認定テスト技術者資格-シラバス(学習事項)・用語集-

略記:TMサンプル問題

日本語版公式のサンプル問題。問題数が少ないのでサクッと。

ISTQB / ASTQB テストマネージャ サンプル問題

GitHub - learnerjstqb/altm_workbook_support: JSTQB® Advanced Level テストマネージャ問題集のサポートページです。

略記:ISTQB TM サンプル問題、ASTQB TM サンプル問題

TM非認定問題集のサポートページに ISTQB / ASTQB のサンプル問題を翻訳したテキストが掲載されています。機械翻訳なので文章は不自然ですが、割り切れば勉強には使えます。

勉強時間と進め方

勉強時間の測定には Studyplus のスマホアプリを利用しました。
学習総合サイト Studyplus(スタディプラス)

2021/02 2021/03 2021/04 2021/05 2021/06 2021/07 2021/08 小計
ソフトウェアテスト12の必勝プロセス 3.0 6.25 4.25 5.0 18.5
基本から学ぶテストプロセス管理 4.75 8.25 13.0
体系的ソフトウェアテスト入門 2.0 9.0 11.0
TMシラバス解説書 2.25 4.0 0.25 2.75 9.25
TMシラバス 1.25 5.25 2.25 8.75
スクエアTM問題集 5.75 8.5 6.75 7.0 4.75 9.75 42.5
TM非認定問題集 1.25 7.5 12.5 8.75 30.0
TM過去問セミナー 1.0 1.0
TMサンプル問題 0.25 0.25
ISTQB TM サンプル問題 6.75 6.75
ASTQB TM サンプル問題 5.75 5.75
小計 11.0 18.75 4.25 18.0 28.75 31.5 34.5 146.75

(単位:時間)

TAの試験直後からTMの試験勉強を開始しました。

過去の受験勉強の成果があるため、以下の内容を並行して進めることにしました。

  • TM過去問セミナー推薦図書を読む
    • 自宅だとまとまった時間を取れないため、本を会社に置いておき、始業前などに読んだ。
  • シラバスを読む
  • 問題集を解く
    • スクエアTM問題集とTM非認定問題集を中心に取り組んだ。
    • サンプル問題などは直前の追い込みで利用した。

TM受験に向けた感触をつかんだことや、他に優先して勉強したいことがあったため、2021/04 の勉強時間は少なめになっています。

2021/05 からTM試験に向けた勉強を再始動しました。問題集はスクエアTM問題集に加え、TM非認定問題集にも取り組みました。通勤時間はスマホで取り組みやすいスクエアTM問題集を、自宅では PC でTM非認定問題集に取り組みました。

COVID-19 の感染拡大に伴い、在宅勤務比率が増え、通勤時間を勉強時間に充てるのは難しくなりましたが、始業前の時間を活用して問題集に取り組み続けました。

TM過去問セミナー推薦図書は1回目でサラッと目を通し、2回目でじっくりと読むつもりでした。ですが、在宅勤務にシフトすることで時間の確保が難しくなったこと、試験合格に向けた勉強という観点では効率が低いことから、残り時間も踏まえ1回目で終了としました。

2021/08 は勉強に集中するための有給休暇も取得し、勉強時間を確保しました。

今回は過去の勉強の成果もあったことから、勉強時間の目標を 100 ~ 150 時間としていました。150 時間には少し届きませんでしたが、ほぼ達成できました。

試験の振り返り

解答ペース

私の場合、3時間の試験時間の内、2時間強で一通り解き、残りの時間で見直しを行いました。解答に自信のない問題は印をつけておき、優先して見直しました。全体の 1/3 程度は見直すことができました。

3時間は長丁場であり、体力と集中力の勝負でした。最初60分の入退出禁止時間を過ぎればトイレ休憩にも行けますが、試験時間は止まりません。その時間を無駄にしたくなかったので、試験前の水分のマネジメントには気を遣いました。

過去の試験では見直しで解答を変更することもありましたが、今回はほとんどありませんでした。このことから手ごたえを感じています。

出題傾向

JSTQBの問題用紙の持ち帰りを認めず、公開もしないというポリシー(JSTQB認定テスト技術者資格-FAQ-)を尊重し、本節をまとめています。このため、具体的なケースには言及せず、どのような勉強が必要かを示すことにしました。

JSTQB認定テスト技術者資格のFAQには以下の記述があります。

JSTQBは、引っかけ問題のようなものを可能な限り排除し、きちんと理解していれば点数が取れるような問題を作成しております。

JSTQB認定テスト技術者資格-FAQ-

問題集にありがちなひっかけ問題はほとんど見当たりませんでした。

ただ、シラバスや問題集を丸暗記していれば解ける問題かというと、そうでもありません。率直なところ、どう勉強すればよいか説明しがたい…と実際の試験問題を解きながら感じました。シラバスを読みこみ、問題集で出題パターンを理解し、実務経験も含めた応用力を効かせて問題を解く、といったところでしょうか。

予防コスト・評価コスト・内部失敗コスト・外部失敗コストを問う問題が数問出題されていました。

テストプロセス改善モデルの特徴を問う問題は1問ぐらいでした。以前は数問出ていた気もするのですが…?

挑戦の振り返り

今回はできることを全てやりつくして試験に臨むことができました。結果がどうあれ、悔いはありません。これで不合格であれば、今後のTM試験は諦めるしかないかも…とすら思っています。

TM試験の合格に近道はありません。地道に積み上げ、運も味方にし、手を伸ばした先に合格があるように思います。この記事を読んでくださった皆様の健闘を祈ります。

更新情報

2021/08/28

スクエアリングサービスの運営の方から、TMシラバス解説書もシラバスの最新版である Version2012.J04 に対応したとご連絡いただきましたので、補足を追記しました。

PostgreSQL のオブジェクト識別子データ型(OID 別名型)と使い方

目的

PostgreSQL には「オブジェクト識別子 (OID)」の別名型として「オブジェクト識別子データ型(OID 別名型)」があります。
8.19. オブジェクト識別子データ型

本記事ではオブジェクト識別子データ型と使い方を中心に解説します。最後にその実装にも踏み込んで解説をします。

前提

OID については下記の解説記事を参照ください。
オブジェクト識別子を活用する | Let's POSTGRES

PostgreSQL 13 で調査を行いました。参照する PostgreSQL 日本語ドキュメントのバージョンは現時点で最新の 12 としています。

オブジェクト識別子データ型の一覧

オブジェクト識別子データ型の一覧はマニュアルに記載されています。PostgreSQL 12 のマニュアルから引用します。

型名 参照 説明 値の例
oid すべて 数値オブジェクト識別子 564182
regproc pg_proc 関数名 sum
regprocedure pg_proc 引数の型を持つ関数 sum(int4)
regoper pg_operator 演算子 +
regoperator pg_operator 引数の型を持つ演算子 *(integer,integer) or -(NONE,integer)
regclass pg_class リレーション名 pg_type
regtype pg_type データ型名 integer
regrole pg_authid ロール名 smithee
regnamespace pg_namespace 名前空間 pg_catalog
regconfig pg_ts_config テキスト検索設定 english
regdictionary pg_ts_dict テキスト検索辞書 simple
8.19. オブジェクト識別子データ型

オブジェクト識別子データ型へのキャスト

オブジェクト識別子データ型へは型キャストの構文でキャストできます。型キャストの構文を以下に示します。

PostgreSQL は型キャストに2つの等価な構文を受け付けます。

CAST ( expression AS type )
expression::type

CAST 構文は SQL に準拠したものです。:: を使用する構文は、PostgreSQL で伝統的に使用されている方法です。

4.2. 評価式

オブジェクトの名称から OID を得る

別名データ型により、オブジェクトの OID 値の検索が簡単になります。例えば、mytable テーブルに関連した pg_attribute 行を確認するには、以下のように記述することができます。

SELECT * FROM pg_attribute WHERE attrelid = 'mytable'::regclass;
8.19. オブジェクト識別子データ型

この例では 'mytable' を regclass にキャストしています。regclass は pg_class を参照しており、リレーション(テーブル、インデックス、ビューなど)の OID に変換できます。

SELECT 句で OID を取得したいときは OID にキャストします。

-- OID にキャストしないと名称を取得する
SELECT 'pg_class'::regclass;

 regclass
----------
 pg_class
(1 row)

-- OID にキャストすれば OID を取得できる
SELECT 'pg_class'::regclass::oid;

 oid
------
 1259
(1 row)

OID からオブジェクトの名称を得る

SELECT oid FROM pg_class WHERE relname = 'pg_class';

 oid
------
 1259
(1 row)

SELECT 1259::regclass;

 regclass
----------
 pg_class
(1 row)

'pg_class' の OID が 1259 であることを確認しました。その 1259 を regclass にキャストすることで、該当するリレーション名の 'pg_class' を取得できました。

システムカタログでのオブジェクト識別子データ型の適用

オブジェクト識別子データ型(8.19. オブジェクト識別子データ型)の「参照」とシステムカタログの列の説明にある「参照先」を比較することで、適用できるケースを判別できます。

一例として pg_cast (51.10. pg_cast) の列をマニュアルで確認します。

システムカタログでのオブジェクト識別子データ型の適用

castsource, casttarget の参照先は pg_type.oid となっています。オブジェクト識別子データ型で regtype の参照は pg_type となっています。このことから、regtype にキャストすることで「データ型名」に変換できるとわかります。

castfunc の参照先は pg_proc.oid となっています。オブジェクト識別子データ型で regprocedure の参照は pg_proc となっています。このことから、regprocedure にキャストすることで「引数の型を持つ関数」に変換できるとわかります。

'text' からのキャストを調べる例で使用方法を示します。

SELECT
  castsource::regtype,
  casttarget::regtype,
  castfunc::regprocedure
FROM
  pg_cast
WHERE
  castsource = 'text'::regtype
ORDER BY
  castsource,
  casttarget;

 castsource |    casttarget     |    castfunc
------------+-------------------+----------------
 text       | "char"            | "char"(text)
 text       | name              | name(text)
 text       | xml               | xml(text)
 text       | character         | -
 text       | character varying | -
 text       | regclass          | regclass(text)
(6 rows)

regproc と regoper 別名型の制限

マニュアルに以下の記述があります。

regproc と regoper 別名型は、一意な(オーバーロードしていない)名前のみを入力として受け入れるため、これらの使用には限度があります。ほとんどの場合、regprocedure または regoperator を使用するのが適切です。

8.19. オブジェクト識別子データ型

この記述を実際の挙動から確認します。

-- pg_proc カタログで pi と sum の定義数を確認する
SELECT
  proname,
  count(*)
FROM
  pg_proc
WHERE
  proname IN ('pi', 'sum')
GROUP BY
  proname;

 proname | count
---------+-------
 pi      |     1
 sum     |     8
(2 rows)

-- pg_proc カタログ内で関数名が一意な場合
SELECT 'pi'::regproc;

 regproc
---------
 pi
(1 row)

-- pg_proc カタログ内で関数名が一意でない場合
SELECT 'sum'::regproc;

ERROR:  more than one function named "sum"
LINE 1: SELECT 'sum'::regproc;

-- 引数の型を指定して regprocedure でキャストする
SELECT 'sum(integer)'::regprocedure;

 regprocedure
--------------
 sum(integer)
(1 row)

regproc では一意な名前を指定しないとエラーになりました。このような場合、マニュアルに記載の通り、引数の型を指定して regprocedure でキャストする必要があります。

キャストの実装と挙動

まず regclass の「入出力変換関数(テキスト形式)」と「データ型変換パス」を実装している関数名について調べます。

「入出力変換関数(テキスト形式)」の説明をマニュアルから引用します。

ユーザ定義データ型では必ず入力関数と出力関数が必要です。 これらの関数は、その型が(ユーザによる入力とユーザへの出力のための)文字列としてどのように表現されるかと、その型がメモリ中でどう構成されるかを決定します。

37.13. ユーザ定義の型

「データ型変換パス」はキャスト可能な型やその変換方法を定義したものです。

-- regclass の入出力変換関数(テキスト形式)を調べる
SELECT
  typinput::oid,
  typinput::regprocedure,
  typoutput::oid,
  typoutput::regprocedure
FROM
  pg_type
WHERE
  typname = 'regclass';

 typinput |      typinput       | typoutput |       typoutput
----------+---------------------+-----------+-----------------------
     2218 | regclassin(cstring) |      2219 | regclassout(regclass)
(1 row)

-- regclass の入出力変換関数(テキスト形式)の関数名を調べる
SELECT
  oid,
  proname,
  prosrc
FROM
  pg_proc
WHERE
  oid IN (2218, 2219);

 oid  |   proname   |   prosrc
------+-------------+-------------
 2218 | regclassin  | regclassin
 2219 | regclassout | regclassout
(2 rows)

-- regclass のデータ型変換パスを調べる
SELECT
  castsource::regtype,
  casttarget::regtype,
  castfunc,
  castfunc::regprocedure,
  castcontext,
  castmethod
FROM
  pg_cast
WHERE
  castsource = 'regclass'::regtype
  OR casttarget = 'regclass'::regtype
ORDER BY
  castsource,
  casttarget;

    castsource     | casttarget | castfunc |    castfunc    | castcontext | castmethod
-------------------+------------+----------+----------------+-------------+------------
 bigint            | regclass   |     1287 | oid(bigint)    | i           | f
 smallint          | regclass   |      313 | int4(smallint) | i           | f
 integer           | regclass   |        0 | -              | i           | b
 text              | regclass   |     1079 | regclass(text) | i           | f
 oid               | regclass   |        0 | -              | i           | b
 character varying | regclass   |     1079 | regclass(text) | i           | f
 regclass          | bigint     |     1288 | int8(oid)      | a           | f
 regclass          | integer    |        0 | -              | a           | b
 regclass          | oid        |        0 | -              | i           | b
(9 rows)

-- text -> regclass のキャストを実行する関数名を調べる
SELECT
  oid,
  proname,
  prosrc
FROM
  pg_proc
WHERE
  oid = 1079;

 oid  | proname  |    prosrc
------+----------+---------------
 1079 | regclass | text_regclass
(1 row)

テキスト入出力のキャスト

regclass のテキストを入出力とするキャストの実装関数を表にまとめます。

目的 関数
入力変換関数(テキスト形式) regclassin
出力変換関数(テキスト形式) regclassout
text ⇒ regclass text_regclass

これらの関数はいずれも下記のソースコード内に存在します。
src/backend/utils/adt/regproc.c

regclassin, text_regclass 共に入力がテキストという点では同じです。そこで、プリントデバッグの手法でどのようなケースにおいて、どちらがコールされるかを調査しました。

結果は以下の通りとなりました。

クエリ 関数
SELECT 'pg_class'::regclass; regclassin
SELECT 'pg_class'::text::regclass; text_regclass
SELECT nextval('foo'); regclassin
SELECT nextval('foo'::text); text_regclass

text_regclass のコメント及びマニュアルの記載より、text_regclass は PostgreSQL 8.1 より前のシーケンス関数の挙動である「動的束縛」を実現するために用意されているようです。詳細はマニュアルの「シーケンス操作関数(9.16. シーケンス操作関数)」に記載されている注記を参照ください。

regclassout のコメントには以下の記載があります。

converts class OID to "class_name"
If OID doesn't match any pg_class entry, return it numerically

これを実際の挙動から確認します。

-- pg_class に実在する OID なら名称に変換される
SELECT 1259::regclass;

 regclass
----------
 pg_class
(1 row)

-- pg_class に実在しない OID なら値のままとなる
SELECT 9999::regclass;

 regclass
----------
 9999
(1 row)

数値でのキャスト

regclass のデータ型変換パスで以下の変換は castmethod = b であり、『型がバイナリを強制しているため、変換が必要ない(引用元:51.10. pg_cast)』となっています。

  • integer ⇒ regclass
  • oid ⇒ regclass
  • regclass ⇒ integer
  • regclass ⇒ oid

『型がバイナリを強制している』が何を指しているかは CREATE CAST の説明を参照ください。

2つのデータ型をバイナリ強制互換とすることができます。これは、関数をまったく呼び出さなくても、「自由に」変換を行うことができることを意味します。これには、対応する値は、同じ内部表現を使用している必要があります。例えば、データ型 text と varchar には、両方向でバイナリ互換性があります。バイナリ強制互換性は必ずしも対称関係ではありません。例えば、現在の実装では xml から text へのキャストは自由に行うことができますが、逆方向では少なくとも構文検査を行う関数が必要です。(2つの型が両方向でバイナリ強制互換であることは、バイナリ互換性と呼ばれます。)

CREATE CAST

oid データ型の実装に関して以下の記述があります。

oid データ型は現在、符号なし4バイト整数として実装されています。

8.19. オブジェクト識別子データ型

これらのことから、regclass も oid と同じ内部表現を持っている、つまり符号なし4バイト整数として実装されていると推測できます。regclass は oid の別名型なので、当然といえるかもしれません。

「真摯さ」とは何か

私は「真摯さ」を「自分の考えに信念(軸、芯)を持ち、それに従った行動をすること」と考えています。それは安易に「バランス」という言葉に逃げないということです。バランスではなく、決断しなければいけません。決断するために自分の信念を持たなければいけません。自分の信念を基準に決断するのです。

私はエンジニアであり、夫であり、父親であります。このいずれかの立場だけを選ぶことはできません。全てにおいて真摯であり続ける必要があります。

エンジニアという立場で真摯さを考えます。

エンジニアは技術のプロフェッショナルです。どのような立場や仕事であれ、常にプロとしての意識を持ち、その仕事に取り組まなければいけません。

例えばシステム構築に携わっているならば、ビジネスをシステムで支える責任があります。システムに対してプロとして真摯に向き合う必要があります。システムが何のために存在しているのか。そのシステムの価値を最大限引き出すために何ができるかを考え抜く。そして決断に基づいて行動します。

「真摯さ」は「真摯さとは何か」を考え続けることでもあります。そして、様々な立場と制約の中で何ができるかを徹底的に考え抜き、行動することです。