投稿日:
毎回忘れるので書いておく
基本は以下の動画の通りでよいが参考程度に途中の写真も置いておく
弦はペグに向けて通し、ペグの反対側を折り曲げる
動画の通りに一回目の巻きは上を通し、以降の巻きは下を通すようにする
最終形態はこんな感じ。飛び出た弦は危ないので切ってある。別に動画のように上に持ち上げてもいいと思うが、購入時点では切ってあったのと安全上の理由もあり、私は切り落としている
余談だが椅子の上に乗せてやると作業しやすい
毎回忘れるので書いておく
基本は以下の動画の通りでよいが参考程度に途中の写真も置いておく
弦はペグに向けて通し、ペグの反対側を折り曲げる
動画の通りに一回目の巻きは上を通し、以降の巻きは下を通すようにする
最終形態はこんな感じ。飛び出た弦は危ないので切ってある。別に動画のように上に持ち上げてもいいと思うが、購入時点では切ってあったのと安全上の理由もあり、私は切り落としている
余談だが椅子の上に乗せてやると作業しやすい
Athenaクエリ周りのメモ。
Amazon Athena とはによると、次のようにあるが、癖があることは覚えていた方が良い。
Amazon Athena は、標準的な SQL を使用して Amazon Simple Storage Service (Amazon S3) 内のデータを直接分析することを容易にするインタラクティブなクエリサービスです。
関数についてはAmazon Athena の関数を見るとよいのだが、Prestoのサイトを見たほうが多分早い。
SELECT
date_parse('2020-01-05T23:21:00.53Z', '%Y-%m-%dT%H:%i:%s.%fZ') AT TIME ZONE 'Asia/Tokyo' AS jst
SELECT
CAST(TBL.TSTMP AS date)
FROM (
SELECT timestamp '2020-11-20 01:00:00' AS TSTMP
) TBL
TO_DATEはtimestampを受け付けないので役に立たない。TO_CHARはドキュメント上扱えるように見えるがフォーマット文字でエラーになる。
以下の様にしてもサポート外の数値型が渡る様で上手くいかない
TO_CHAR(year(TBL.TSTMP)) || '-' || TO_CHAR(month(TBL.TSTMP)) || '-' || TO_CHAR(day_of_month(TBL.TSTMP))
date YYYY-MM-DDとして、型を明示しないと上手くいかない
SELECT
*
FROM
TBL
WHERE
TBL.createAt = date '2023-11-22'
以前記事にした、加古川総合文化センターにて行われた「いとうのいぢ展 ぜんぶ!」で注文した版画が遂に到着した。
これは私にとっては初の版画となる。版画といえば、今から20年かそのくらい前には版画屋という悪質商人がいるという噂で良いイメージがなかったが、今ではそういう話も聞かなくなった気がするのできっと良い世界になったのだと思う。個人的には版画自体は職業イラストレーターの貴重な収入源の一つになっていると考えている。
まぁ、前振りは程々にしておき、こちらが今回届いた版画だ。プチプチで二重巻きにされてた上に、角には段ボールが嵌めてあり、更に額縁そのものは段ボールで包装されており、更にその中もビニールで保護されているという、非常に厳重に作品が保護されていて、素直に凄いと思った。まだこの写真の時点ではビニールで包装された状態だ。
しかし買う前のサンプルで解っていたことだが、やはり加古川市章はない。
これはビニール包装を解いた裏側だ。ぶら下げる金具の様なものと謎の紐が見えるが、これはぶら下げる金具ではなく紐通しらしい。
この紐を使ってフックなどにぶら下げて飾る用途のようだ。よく見たら作品に添付されていた説明書にもそう書かれていた。作品を飾るのにちょうどいい塩梅で設定されているらしく、解かないほうがいいらしい。ただ金具類は調子に応じて調整してとあったので、左下の緩んでいる金具だけドライバーで締めておいた。
作品保証書までついていた。エンボス加工がされており、高級感があるが、恐らくは偽造防止用だろう。エディションナンバーまで刻まれていて、これが私の元に届いたものであることを正に証明している。
ひとまず撮影台の上に置いておいても仕方がないので飾ってみることにした。フックはあるのだが、程よい高さに丁度いいスペースがないのと、立てかけていた方が額縁らしい気がしたので壁に立てかけてみた。部屋の明かりの関係で反射するため、暗めの写真になってしまったがいい感じだ。下に並んでいるのはアートタイルで、こちらは会場で直接購入したものだ。版画は会場での直接販売がなかったので、会場での予約販売を利用した。
因みに版画とは言うが、いわゆる木彫りの板にインクを塗って紙に押し付けるようなものではなく、特殊印刷と呼ばれるものである。例えばこの作品には88グラフという印刷技法が使われている。一般的な版画作品はシルクスクリーンという技法がベースになっていると聞くが、こちらも例にもれずシルクスクリーンを利用しているようだ。
大和グランド株式会社の説明によるとシルクスクリーン印刷は一般商業印刷ではほとんど用いられず、特殊な印刷か、軽印刷の分野で多用されているとのことだった。ステッカー、Tシャツ、看板、計器版、プリント回路などの印刷に用いられるケースが多いようである。印刷対象や塗料の種類が豊富なのが強みらしいので、複合的な印刷技術を用いる版画向きの手法なのかもしれない。
ただ今回の版画はアールジュネスで売られているものと比べると幾分か安く見えたので、廉価な印刷技法を使うなど、どこかでコストカットを行っているのだろうか?そこは少しだけ気になった。確か桁が違ったような…。
私の部屋には他にもポスターやタペストリーといった美術品があるが、この版画はそれらとは一線を画した美術品だと思うので、墓に入るまで持ち続けていたいものである。何よりこれは兵庫県の加古川市をモチーフにしたいとうのいぢ先生の作品だ。神戸在住の私としても加古川の宝の一つと言える。
因みにこのキャラクターの名前はかこのちゃんに内定している。なお加古川市章を身に着けたかこのちゃんのフルサイズイラストが見れるのは私が知りうる限り、加古川市のサイトや、加古川市の関連施設のみで、恐らく商業的なグッズ化などはされていない。
JestからNode.js組み込みのテストランナーに移行する時の方法や注意点をまとめたメモ
describe(name, fn), it(name, fn, timeout?), test(name, fn, timeout?)beforeAll(fn, timeout?), afterAll(fn, timeout?), beforeEach(fn, timeout?), afterEach(fn, timeout?).toBe(value), .not.toBe(value).toStrictEqual(value), .not.toStrictEqual(value).toHaveLength(number), .toBeNull(), .toBeUndefined(), .toBeNaN().toBeTruthy().toBeInstanceOf(Class).toThrow, not.toThrow
expect.arrayContaining(array), expect.objectContaining(object), expect.stringContaining(string)jest.spyOn(object, methodName, accessType?)
.toHaveBeenCalled(), .toHaveBeenCalledTimes(number).toHaveBeenCalledWith(arg1, arg2, ...)jest.fn(implementation?)jest.useFakeTimers(fakeTimersConfig?), jest.runAllTimers()jest.useRealTimers()mockFn.mockClear()mockFn.mockReset()
| Env | ver |
|---|---|
| Node.js | 20.8.0 |
| Jest | 29.7 |
英語圏ではNode.js built-in test runnerとか呼ばれている存在で、Node.jsの組み込みテストランナーのこと。恐らくDenoのテストランナーに対抗して生まれた気配がする(Node.jsはDenoに機能追加があると真似する傾向があるため)
Node.jsの組み込みテストランナーは機能が二分されており、テストランナーとアサートに分かれている。Jestみたいにエコシステムが発達しておらず、標準ではdescribeなどはimportする必要がある。TypeScriptをテストする場合は間にレジスター[1]を嚙ます必要がある。噛まし方はswc/jestでESM, CJS混在のコードをJestを使ってテストする有力な方法は今のところ多分ないに書いた。
describe, it, beforeAll, afterAll, beforeEach, afterEach辺りは違和感がなかったが、それ以外は軒並み互換性がないので大きく書き換えが必要だと感じた。便利なMatcherは完膚なきまでに全滅している。お陰で覚えることが減ったのは逆に良くなったと感じる
なお、not始まりの機能は実際の動作を確認しておらず、Jestと同じ機能かどうかは確認していないことに留意すること
describe(name, fn), it(name, fn, timeout?), test(name, fn, timeout?)Node.jsのTest機能では、以下となる
describe([name][, options][, fn])it([name][, options][, fn])test([name][, options][, fn])基本的な差はないがJestにあったtimeout引数はNode.jsではoptionsパラメーターで設定するようになっている模様。今回調べるまで存在自体を知らなかったのもあり、このtimeoutがJestと同じ機能かどうかは確認していない
import { describe, it } from 'node:test';
describe('hoge', () => {
it('hoge', () => {
// ここにテストコード
});
it.todo('piyo');
});
beforeAll(fn, timeout?), afterAll(fn, timeout?), beforeEach(fn, timeout?), afterEach(fn, timeout?)Node.jsのTest機能では、以下となる
before([fn][, options])after([fn][, options])beforeEach([fn][, options])afterEach([fn][, options])基本的な差はないがJestにあったtimeout引数はNode.jsではoptionsパラメーターで設定するようになっている模様。今回調べるまで存在自体を知らなかったのもあり、このtimeoutがJestと同じ機能かどうかは確認していない
+import { after, before, beforeEach, afterEach, describe } from 'node:test';
+
describe('test', () => {
- beforeAll(() => {
+ before(() => {
console.log('before');
});
beforeEach(() => {
console.log('beforeEach');
});
afterEach(() => {
console.log('afterEach');
});
- afterAll(() => {
+ after(() => {
console.log('after');
});
});
.toBe(value), .not.toBe(value)Node.jsのTest機能では、以下となる
assert.strictEqual(actual, expected[, message])assert.notStrictEqual(actual, expected[, message])+import { describe, it } from 'node:test';
+import assert from 'node:assert';
+
describe('test', () => {
it('test', () => {
const actual = 123;
- expect(actual).toBe(123);
+ assert.deepStrictEqual(actual, 123);
});
});
.toStrictEqual(value), .not.toStrictEqual(value)Node.jsのTest機能では、以下となる
assert.deepStrictEqual(actual, expected[, message])assert.notDeepStrictEqual(actual, expected[, message])+import { describe, it } from 'node:test';
+import assert from 'node:assert';
+
describe('test', () => {
it('test', () => {
const actual = {
hoge: {
piyo: {
id: 1,
value: 'one'
}
},
fuga: [[123, 456], 'ABC', 'EFG']
};
- expect(actual).toStrictEqual({
+ assert.deepStrictEqual(actual, {
hoge: {
piyo: {
id: 1,
value: 'one'
}
},
fuga: [[123, 456], 'ABC', 'EFG']
});
});
});
.toHaveLength(number), .toBeNull(), .toBeUndefined(), .toBeNaN()Node.jsのTest機能では、assert.strictEqual()となる
+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
describe('test', () => {
it('test', () => {
const arr = [1, 2, 3];
const undef = undefined;
const nil = null;
const nan = NaN;
- expect(arr).toHaveLength(3);
- expect(undef).toBeUndefined();
- expect(nil).toBeNull();
- expect(nan).toBeNaN();
+ assert.strictEqual(arr.length, 3);
+ assert.strictEqual(undef, undefined);
+ assert.strictEqual(nil, null);
+ assert.strictEqual(nan, NaN);
});
});
.toBeTruthy()Node.jsのTest機能では、以下となる
assert.ok(value[, message])否定版は不明
+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
describe('test', () => {
it('test', () => {
- expect(true).toBeTruthy();
- expect({}).toBeTruthy();
- expect([]).toBeTruthy();
- expect(42).toBeTruthy();
- expect('0').toBeTruthy();
- expect('false').toBeTruthy();
- expect(new Date()).toBeTruthy();
- expect(-42).toBeTruthy();
- expect(12n).toBeTruthy();
- expect(3.14).toBeTruthy();
- expect(Infinity).toBeTruthy();
- expect(-Infinity).toBeTruthy();
+ assert.ok(true);
+ assert.ok({});
+ assert.ok([]);
+ assert.ok(42);
+ assert.ok('0');
+ assert.ok('false');
+ assert.ok(new Date());
+ assert.ok(-42);
+ assert.ok(12n);
+ assert.ok(3.14);
+ assert.ok(Infinity);
+ assert.ok(-Infinity);
});
});
.toBeInstanceOf(Class)Node.jsのTest機能では、assert.ok()となる
結果がTruthyであればなんでもpassするので注意
+import { describe, it } from 'node:test';
+import assert from 'node:assert';
+
describe('test', () => {
it('test', () => {
const actual = new Error('hoge');
- expect(actual).toBeInstanceOf(Error);
+ assert.ok(actual instanceof Error);
});
});
.toThrow, not.toThrowNode.jsのTest機能では、以下となる
assert.throws(fn[, error][, message])assert.doesNotThrow(fn[, error][, message])Jestより便利になっており、Error型以外も扱えるので後述する
+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
describe('test', () => {
it('test', () => {
const err = new Error('test');
- expect(() => {
+ assert.throws(() => {
throw err;
- }).toThrow(err);
+ }, err);
});
});
Jestの`.toThrow()はError型以外を扱うことができず、オブジェクトをThrowするようなコードではエラーになる
describe('test', () => {
it('test', () => {
const obj = { id: 1, value: 'hoge' };
// このテストは失敗する。またTypeScriptの型エラーにもなる
expect(() => {
throw obj;
}).toThrow(obj);
// このテストは失敗する。またTypeScriptの型エラーにもなる
expect(() => {
throw obj;
}).toThrow({ id: 1, value: 'hoge' });
});
});
しかしNode.jsであればこれはエラーにならない。例えば次のテストコードは成功する
import { describe, it, mock } from 'node:test';
import assert from 'node:assert';
describe('test', () => {
it('test', () => {
const obj = { id: 1, value: 'hoge' };
assert.throws(() => {
throw obj;
}, obj);
assert.throws(
() => {
throw obj;
},
{ id: 1, value: 'hoge' }
);
});
});
expect.arrayContaining(array), expect.objectContaining(object), expect.stringContaining(string)恐らく非対称マッチャーはないので自分でロジックを書いてassert.strictEqual()で判定するしかないと思われる。元々微妙な機能だったのでやむなし
jest.spyOn(object, methodName, accessType?)Node.jsのTest機能では、node:testからmockをimportして以下を使う
mock.method(object, methodName[, implementation][, options])+import { describe, it, mock } from 'node:test';
+
describe('test', () => {
it('test', () => {
- jest.spyOn(console, 'log');
+ mock.method(console, 'log');
});
});
例えば以下のようにテストコードを書いた場合、execSync()が実際の挙動で動作してしまい、テストとして機能しない。
import { describe, it, mock } from 'node:test';
import assert from 'node:assert';
import child_process, { execSync } from 'node:child_process';
const mockedExecSync = mock.method(child_process, 'execSync');
describe('execSync', () => {
it('execSyncが正しい引数で呼ばれること', () => {
execSync('false');
assert.strictEqual(mockedExecSync.mock.calls[0].arguments[0], 'false');
});
});
このような場合、以下のようにmock.method()の第三引数を指定してやると封じることができる。単体テストの観点では基本的に第三引数には空関数を入れておくのが望ましいだろう。
import { describe, it, mock } from 'node:test';
import assert from 'node:assert';
import child_process, { execSync } from 'node:child_process';
- const mockedExecSync = mock.method(child_process, 'execSync');
+ const mockedExecSync = mock.method(child_process, 'execSync', () => {});
describe('execSync', () => {
it('execSyncが正しい引数で呼ばれること', () => {
execSync('false');
assert.strictEqual(mockedExecSync.mock.calls[0].arguments[0], 'false');
});
});
module.exportsされている関数のモックimport foo from 'foo';形式でmock.method()の第一引数を埋める
import { describe, it, mock } from 'node:test';
import assert from 'node:assert';
import child_process, { execSync } from 'node:child_process';
const mockedExecSync = mock.method(child_process, 'execSync', () => {});
describe('execSync', () => {
it('execSyncが正しい引数で呼ばれること', () => {
execSync('false');
assert.strictEqual(mockedExecSync.mock.calls[0].arguments[0], 'false');
});
});
上記が正常に動作することはNode.js v20.0.0時点のコードで確認している
以下のようにmock.method()の第一引数にGlobal objectを設定すればよい
import { describe, it, mock } from 'node:test';
import assert from 'node:assert';
describe('exit', () => {
// exitが実際に走って落ちるのでmock.methodの第三引数を指定している
const mockedExit = mock.method(process, 'exit', () => {});
it('call exit', () => {
process.exit(1);
assert.strictEqual(mockedExit.mock.calls.length, 1);
});
});
ファイルモックをする手段がないので正攻法では無理そう
https://github.com/nodejs/help/issues/4298
2024-10-15追記
Node.js v22.3.0でテスト走行時に--experimental-test-module-mocksを渡すことで近いことができるようになった模様だが、試したところ上手く動かないし、spy的な使い方はできなさそうだ。mock.method()との組み合わせも試してみたが、上手くいかなかった。
実装例(Object)
export const Hoge = {
validateFoo() {
// 例外を飛ばす可能性のある何かの処理
},
hoge() {
Hoge.validateFoo();
return 1;
},
};
実装例(Namespace)
export namespace Hoge {
export const validateFoo = () => {
// 例外を飛ばす可能性のある何かの処理
};
export const hoge = () => {
validateFoo();
return 1;
};
}
実装例に対するテストコード
ObjectもNamespaceも同じ書き方でテスト可能
import { describe, it } from 'node:test';
import assert from 'node:assert';
import { Hoge } from './hoge';
describe('hoge', () => {
it('validateFooが例外をスローした場合、例外がスローされること', (t) => {
t.mock.method(Hoge, 'validateFoo', () => {
throw new Error('foo');
});
assert.throws(() => {
Hoge.hoge();
}, Error('foo'));
});
it('全ての関数が正常終了した場合、戻り値を返すこと', () => {
const actual = Hoge.hoge();
assert.strictEqual(actual, 1);
});
});
.toHaveBeenCalled(), .toHaveBeenCalledTimes(number)Node.jsのTest機能では、assert.strictEqual()でモックから生えてるやつを調べる。returnも同様の手法で実現できる
+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
describe('test', () => {
it('test', () => {
- const spiedConsoleLog = jest.spyOn(console, 'log');
+ const mockedConsoleLog = mock.method(console, 'log');
console.log();
- expect(spiedConsoleLog).toHaveBeenCalled();
- expect(spiedConsoleLog).toHaveBeenCalledTimes(1);
+ assert.deepStrictEqual(mockedConsoleLog.mock.calls.length, 1);
});
});
.toHaveBeenCalledWith(arg1, arg2, ...)Node.jsのTest機能では、assert.strictEqual()でモックから生えてるやつを調べる。returnも同様の手法で実現できる。
Jestでは.toEqual()処理されるがNode.jsの組み込みテストランナーの場合、厳密比較ができるので便利
+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
describe('test', () => {
it('test', () => {
- const spiedConsoleLog = jest.spyOn(console, 'log');
+ const mockedInfo = mock.method(console, 'log');
console.log('test');
- expect(spiedConsoleLog).toHaveBeenCalledWith('test');
+ assert.deepStrictEqual(mockedInfo.mock.calls[0].arguments[0], 'test');
});
});
jest.fn(implementation?)Node.jsのTest機能では、以下となる
mock.fn([original[, implementation]][, options])+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
+// 動作確認用の関数
const testTarget = (cbParam: string, callbackFn: (param: string) => number) => {
return callbackFn(cbParam);
};
describe('test', () => {
it('test', () => {
- const mockFn = jest.fn((_: string) => {
+ const mockFn = mock.fn((_: string) => {
return 5;
});
const actual = testTarget('hoge', mockFn);
- expect(mockFn).toBeCalledWith('hoge');
- expect(mockFn).toReturnWith(5);
- expect(actual).toBe(5);
+ assert.deepStrictEqual(mockFn.mock.calls[0].arguments[0], 'hoge');
+ assert.deepStrictEqual(mockFn.mock.calls[0].result, 5);
+ assert.deepStrictEqual(actual, 5);
});
});
jest.useFakeTimers(fakeTimersConfig?), jest.runAllTimers()Node.jsのTest機能では、以下となる
mock.timers.enable([timers])mock.timers.runAll()+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
+describe('test', () => {
- jest.useFakeTimers();
+ mock.timers.enable();
+ it('test', () => {
- const mockFn = jest.fn();
+ const mockFn = mock.fn();
setTimeout(() => {
mockFn();
}, 9999);
- expect(mockFn).not.toHaveBeenCalled();
- jest.runAllTimers();
- expect(mockFn).toHaveBeenCalledTimes(1);
+ assert.deepStrictEqual(mockFn.mock.calls.length, 0);
+ mock.timers.runAll();
+ assert.deepStrictEqual(mockFn.mock.calls.length, 1);
});
});
jest.useRealTimers()Node.jsのTest機能では、以下となる
mock.timers.reset()+import { mock } from 'node:test';
-jest.useRealTimers();
+mock.timers.reset();
mockFn.mockClear()Node.jsのTest機能では、以下となる
ctx.resetCalls()+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
describe('test', () => {
it('test', () => {
- const mockFn = jest.fn((param: string) => `<${param}>`);
+ const mockFn = mock.fn((param: string) => `<${param}>`);
mockFn('hoge');
- expect(mockFn).toHaveBeenCalledTimes(1);
- expect(mockFn).toReturnWith('<hoge>');
+ assert.deepStrictEqual(mockFn.mock.calls.length, 1);
+ assert.deepStrictEqual(mockFn.mock.calls[0].result, '<hoge>');
- mockFn.mockClear();
+ mockFn.mock.resetCalls();
- expect(mockFn).toHaveBeenCalledTimes(0);
+ assert.deepStrictEqual(mockFn.mock.calls.length, 0);
mockFn('piyo');
- expect(mockFn).toHaveBeenCalledTimes(1);
- expect(mockFn).toReturnWith('<piyo>');
+ assert.deepStrictEqual(mockFn.mock.calls.length, 1);
+ assert.deepStrictEqual(mockFn.mock.calls[0].result, '<piyo>');
});
});
mockFn.mockReset()Node.jsのTest機能では、以下となる
mockFn.mock.restore()振る舞いが微妙に違うため後述する
+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
describe('test', () => {
it('test', () => {
- const spiedConsoleLog = jest
- .spyOn(console, 'log')
- .mockImplementation((param: any) => {
- return `<${param}>`;
- });
+ const mockedConsoleLog = mock.method(console, 'log', (param: any) => {
+ return `<${param}>`;
+ });
console.log('hoge');
- expect(spiedConsoleLog).toHaveBeenCalledTimes(1);
- expect(spiedConsoleLog).toReturnWith('<hoge>');
+ assert.deepStrictEqual(mockedConsoleLog.mock.calls.length, 1);
+ assert.deepStrictEqual(mockedConsoleLog.mock.calls[0].result, '<hoge>');
- spiedConsoleLog.mockReset();
+ mockedConsoleLog.mock.restore();
});
});
但しJestとNode.jsのTest機能では微妙に差異がある
例えばJestでは以下の実装が正しくPASSするが
describe('test', () => {
it('test', () => {
const mockFn = jest
.spyOn(console, 'log')
.mockImplementation((param: any) => {
return `<${param}>`;
});
console.log('hoge');
expect(mockFn).toHaveBeenCalledTimes(1);
expect(mockFn).toReturnWith('<hoge>');
mockFn.mockReset();
expect(mockFn).toHaveBeenCalledTimes(0);
console.log('piyo');
expect(mockFn).toHaveBeenCalledTimes(1);
expect(mockFn).not.toHaveBeenCalledWith();
expect(mockFn).toReturnWith(undefined);
});
});
Node.jsで以下の実装を書いても同じように機能しない
import { describe, it, mock } from 'node:test';
import assert from 'node:assert';
describe('test', () => {
it('test', () => {
const mockFn = mock.method(console, 'log', (param: any) => {
return `<${param}>`;
});
console.log('hoge');
assert.deepStrictEqual(mockFn.mock.calls.length, 1);
assert.deepStrictEqual(mockFn.mock.calls[0].result, '<hoge>');
mockFn.mock.resetCalls();
mockFn.mock.restore();
assert.deepStrictEqual(mockFn.mock.calls.length, 0);
console.log('piyo');
// 以降のテストはいずれも落ちる
assert.deepStrictEqual(mockFn.mock.calls.length, 1);
assert.deepStrictEqual(mockFn.mock.calls[0].result, '<piyo>');
});
});
但しモック実装を削除したうえで再度呼び出すという行為には意味がないので、特に問題にはならないと思われる
it([name][, options][, fn])の第三引数のコールバックの第一引数にはTestContextが入っており、これを使ってモックすることもできる
これを使う場合、スコープアウトでモックが復元されるため、例えば以下のような関数をテストするときに便利である。
実装
export namespace Hoge {
export const validateFoo = () => {
// 例外を飛ばす可能性のある何かの処理
};
export const validateBar = () => {
// 例外を飛ばす可能性のある何かの処理
};
export const validateBaz = () => {
// 例外を飛ばす可能性のある何かの処理
};
export const hoge = () => {
validateFoo();
validateBar();
validateBaz();
return 1;
};
}
テストコード
import { describe, it } from 'node:test';
import assert from 'node:assert';
import { Hoge } from './hoge';
describe('hoge', () => {
it('validateFooが例外をスローした場合、例外がスローされること', (t) => {
t.mock.method(Hoge, 'validateFoo', () => {
throw new Error('foo');
});
assert.throws(() => {
Hoge.hoge();
}, Error('foo'));
});
it('validateBarが例外をスローした場合、例外がスローされること', (t) => {
t.mock.method(Hoge, 'validateBar', () => {
throw new Error('bar');
});
assert.throws(() => {
Hoge.hoge();
}, Error('bar'));
});
it('validateBazが例外をスローした場合、例外がスローされること', (t) => {
t.mock.method(Hoge, 'validateBaz', () => {
throw new Error('baz');
});
assert.throws(() => {
Hoge.hoge();
}, Error('baz'));
});
it('全ての関数が正常終了した場合、戻り値を返すこと', () => {
const actual = Hoge.hoge();
assert.strictEqual(actual, 1);
});
});
ヘッドホンは電池が切れると使えなくなる、最早これは世間の常識だと思います。しかし世の中には電池が切れないヘッドホンがなんと存在します。恐らく若い人の中には知らない人がいたり、そうでなくても忘れている人も少なくはないでしょう。
今日ふと街中を歩いていると街中利用にしては見慣れないヘッドホンをつけている人を見かけました。どう見ても赤帯だったので歩く速度を速め、追い抜きざまに見てみると、なんと赤帯でした。まさか街中で赤帯をつけてる人を見ることになるとは思わず、だいぶ驚きました。
今やイヤホンジャックがついたスマホはレアなので刺しているとしたらiPodやWalkman的な何かでしょうか…。それも変換プラグがないと使えないはずです。まさかヘッドホン側のプラグを取り換えてるのでしょうか…。
個人的に今の時代に普通のヘッドホンを屋外、それも街中で使っている人がいるのは驚きでした。それも赤帯をです。
因みに私はプラグがないスマホを使っている関係でSONY WI-XB400を利用しています。どっちかというとプラグがないからというよりかは、過去に有線を使っていた時に人混みで他の人に引っかかって断線した経験があるので変えた感じですが…。
ただこのイヤホンも終売なので、次どうするかが悩ましいところです。紛失防止や、取り外し容易性の観点からネックバンド式がいいんですよね。例えば人とちょっと話すときに首にぶら下げておけるのは結構便利なので。ストックとして数本持っておくのもなくはないとは思いますが…。
因みに家の中ではSONY MDR-XB55をUSB-C変換アダプタを通じて使っている他、PCではMDR-CD900ST(赤帯)を使っているので、「電池切れのないヘッドホン」を使っています。外ではUSB-C変換アダプタが折れる可能性があるのと、3極プラグではスマホ音楽プレイヤーの制御ができないので使っていません。
ところで全然関係ないですが、最近イヤホンのことをヘッドホンと呼ぶ風潮について、個人的にはあまり気に入ってません。というか、これに限らず同系統の名称を何か特定の名称に寄せる現象ってある気がします(恐らく細分化されていると判断できないのでしょう)
しかし一体、件の人は何にヘッドホンをどう刺してつかっていたのでしょうか?ちょっと気になりました。