rex0220 アプリマイスター・レイで、kintone アプリのテストデータを生成してみます。
概要
アプリを作成してプラグインのテストを行う場合、まとまった数のテストデータが必要です。
rex0220 アプリマイスター・レイで、顧客アプリを作成して、テストデータを1,000件生成してみます。
- 作成した顧客マスタとテストデータ
作成手順
- 顧客マスタ作成
- テストデータ生成
- 生成されたテストデータを見ると、顧客名の重複が多い
- 再調整を繰り返し
顧客マスタ作成
顧客マスタアプリを作成
・顧客コード: "A0001", "A0002", ...
・顧客名: "織田信長", "徳川 家康", ...
・顧客ランク: ドロップダウン "A","B","C"
他に顧客マスタに必要な項目を追加
/**
* 🦊 kintone App Meister Ray's Work
* Project: 顧客マスタ構築
*/
(async () => {
try {
console.log('🦊 レイ: 顧客マスタアプリの構築を開始します!');
// -------------------------------------------------------
// 1. 新規アプリの作成(プレビュー)
// -------------------------------------------------------
const createAppBody = { name: '顧客マスタ' };
const createResp = await kintone.api(kintone.api.url('/k/v1/preview/app', true), 'POST', createAppBody);
const appId = createResp.app;
console.log(`Step 1: アプリの枠を作成しました... App ID: ${appId}`);
// -------------------------------------------------------
// 2. フィールドの追加
// -------------------------------------------------------
const fieldsBody = {
app: appId,
properties: {
// --- 基本情報 ---
'顧客コード': {
type: 'SINGLE_LINE_TEXT',
label: '顧客コード',
code: '顧客コード',
unique: true, // 重複禁止
required: true, // 必須
minLength: '1'
},
'顧客名': {
type: 'SINGLE_LINE_TEXT',
label: '顧客名',
code: '顧客名',
required: true
},
'顧客ランク': {
type: 'DROP_DOWN',
label: '顧客ランク',
code: '顧客ランク',
options: {
'A': { label: 'A', index: 0 },
'B': { label: 'B', index: 1 },
'C': { label: 'C', index: 2 }
},
defaultValue: 'C',
required: true
},
// --- 連絡先・所在地情報(あると便利な項目を追加しました!) ---
'郵便番号': {
type: 'SINGLE_LINE_TEXT',
label: '郵便番号',
code: '郵便番号',
maxLength: '8'
},
'住所': {
type: 'SINGLE_LINE_TEXT',
label: '住所',
code: '住所'
},
'電話番号': {
type: 'LINK',
label: '電話番号',
code: '電話番号',
protocol: 'CALL'
},
'メールアドレス': {
type: 'LINK',
label: 'メールアドレス',
code: 'メールアドレス',
protocol: 'MAIL'
},
'担当者名': {
type: 'SINGLE_LINE_TEXT',
label: '担当者名',
code: '担当者名'
},
// --- 管理情報 ---
'締め日': {
type: 'DROP_DOWN',
label: '締め日',
code: '締め日',
options: {
'末日': { label: '末日', index: 0 },
'20日': { label: '20日', index: 1 },
'10日': { label: '10日', index: 2 },
'その他': { label: 'その他', index: 3 }
},
defaultValue: '末日'
}
}
};
await kintone.api(kintone.api.url('/k/v1/preview/app/form/fields', true), 'POST', fieldsBody);
console.log('Step 2: フィールド設定完了。連絡先情報も追加しておきました!');
// -------------------------------------------------------
// 3. アプリのレイアウト設定
// -------------------------------------------------------
const layoutBody = {
app: appId,
layout: [
{
type: 'ROW',
fields: [
{ type: 'SINGLE_LINE_TEXT', code: '顧客コード', size: { width: 200 } },
{ type: 'SINGLE_LINE_TEXT', code: '顧客名', size: { width: 300 } },
{ type: 'DROP_DOWN', code: '顧客ランク', size: { width: 150 } }
]
},
{ type: 'ROW', fields: [{ type: 'HR', size: { width: 600 } }] }, // 区切り線
{ type: 'ROW', fields: [{ type: 'LABEL', label: '▼ 所在地・連絡先' }] },
{
type: 'ROW',
fields: [
{ type: 'SINGLE_LINE_TEXT', code: '郵便番号', size: { width: 150 } },
{ type: 'SINGLE_LINE_TEXT', code: '住所', size: { width: 400 } }
]
},
{
type: 'ROW',
fields: [
{ type: 'LINK', code: '電話番号' },
{ type: 'LINK', code: 'メールアドレス' }
]
},
{
type: 'ROW',
fields: [
{ type: 'SINGLE_LINE_TEXT', code: '担当者名' },
{ type: 'DROP_DOWN', code: '締め日' }
]
}
]
};
await kintone.api(kintone.api.url('/k/v1/preview/app/form/layout', true), 'PUT', layoutBody);
console.log('Step 3: レイアウト設定完了');
// -------------------------------------------------------
// 4. 一覧設定
// -------------------------------------------------------
const viewsBody = {
app: appId,
views: {
'一覧': {
type: 'LIST',
name: '一覧',
index: 0,
filterCond: '',
sort: '顧客コード asc',
fields: ['顧客コード', '顧客ランク', '顧客名', '電話番号', '担当者名']
}
}
};
await kintone.api(kintone.api.url('/k/v1/preview/app/views', true), 'PUT', viewsBody);
console.log('Step 4: 一覧設定完了');
// -------------------------------------------------------
// 5. アプリの公開 (Deploy)
// -------------------------------------------------------
console.log('Step 5: アプリの公開処理を実行中...');
await kintone.api(kintone.api.url('/k/v1/preview/app/deploy', true), 'POST', { apps: [{ app: appId }] });
// -------------------------------------------------------
// 完了メッセージ
// -------------------------------------------------------
console.log('-------------------------------------------------------');
console.log(`🎉 レイ: 作成完了です!`);
console.log(`新規作成されたアプリID: ${appId}`);
console.log('作成されたアプリを開いて、レイアウトを確認してみてください。');
console.log('-------------------------------------------------------');
} catch (error) {
console.error('🦊 レイ: おっと、エラーが発生しました。一緒に確認しましょう。', error);
if (error.error) console.error(JSON.stringify(error.error, null, 2));
}
})();
テストデータ生成コード
最終的に重複のないテストデータ生成コード
/**
* 🦊 kintone App Meister Ray's Work
* Project: 顧客マスタ テストデータ生成 (完全ユニーク版)
* Description: 同姓同名が一切ない1000件のデータを生成します
*/
(async () => {
const appId = kintone.app.getId();
if (!appId) {
console.error('🦊 レイ: アプリの画面を開いてから実行してください!');
return;
}
console.log(`🦊 レイ: アプリ(ID: ${appId}) に、名前の重複がない1000件を生成します...`);
// --- 1. データ生成用の素材 ---
const lastNames = [
"佐藤", "鈴木", "高橋", "田中", "伊藤", "渡辺", "山本", "中村", "小林", "加藤",
"吉田", "山田", "佐々木", "山口", "松本", "井上", "木村", "林", "斎藤", "清水",
"山崎", "森", "池田", "橋本", "阿部", "石川", "山下", "中島", "石井", "小川",
"前田", "岡田", "長谷川", "藤田", "後藤", "近藤", "村上", "遠藤", "青木", "坂本",
"斉藤", "福田", "太田", "西村", "藤井", "金子", "和田", "中山", "三浦", "吉野",
"荒木", "上田", "小野", "菊地", "佐野", "柴田", "菅原", "高木", "千葉", "中川",
"西田", "野口", "馬場", "平野", "藤本", "松田", "水野", "安田", "山内", "横山",
"芦田", "新井", "岩田", "内田", "大島", "大野", "岡本", "片山", "川口", "北村",
"工藤", "久保", "古賀", "小島", "酒井", "桜井", "沢田", "島田", "杉山", "高田",
"武田", "谷口", "辻", "中野", "野村", "服部", "原", "原田", "樋口", "星野"
];
const firstNames = [
"翔太", "大輔", "健太", "誠", "直樹", "達也", "剛", "拓哉", "亮太", "一平",
"陽菜", "愛", "美咲", "知花", "結衣", "美優", "七海", "里奈", "花子", "未来",
"蓮", "大和", "湊", "陽翔", "悠真", "結菜", "莉子", "芽依", "咲良", "紬",
"一郎", "次郎", "三郎", "四郎", "五郎", "信長", "秀吉", "家康", "政宗", "幸村",
"浩一", "健一", "次郎", "三郎", "四郎", "賢二", "修平", "大樹", "達郎", "哲也",
"直人", "秀樹", "浩", "博", "学", "充", "稔", "康夫", "雄大", "洋介",
"彩", "香織", "加奈", "久美子", "早紀", "里美", "志帆", "朋子", "直美", "奈緒",
"晴香", "瞳", "麻衣", "真由美", "美香", "恵", "由佳", "洋子", "理恵", "玲奈",
"碧", "蒼", "樹", "陽", "朝陽", "日向", "奏太", "伊織", "律", "瑛太"
];
const ranks = ["A", "B", "C"];
const closings = ["末日", "20日", "10日", "その他"];
const prefectures = [
"北海道", "青森県", "岩手県", "宮城県", "秋田県", "山形県", "福島県",
"茨城県", "栃木県", "群馬県", "埼玉県", "千葉県", "東京都", "神奈川県",
"新潟県", "富山県", "石川県", "福井県", "山梨県", "長野県", "岐阜県",
"静岡県", "愛知県", "三重県", "滋賀県", "京都府", "大阪府", "兵庫県",
"奈良県", "和歌山県", "鳥取県", "島根県", "岡山県", "広島県", "山口県",
"徳島県", "香川県", "愛媛県", "高知県", "福岡県", "佐賀県", "長崎県",
"熊本県", "大分県", "宮崎県", "鹿児島県", "沖縄県"
];
const pick = (arr) => arr[Math.floor(Math.random() * arr.length)];
const randNum = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
// --- 2. 重複なしで1000件のデータを作成 ---
const records = [];
const generatedNames = new Set(); // 生成済み名前管理用
let counter = 1;
// recordsが1000件になるまで繰り返す
while (records.length < 1000) {
const ln = pick(lastNames);
const fn = pick(firstNames);
const fullName = `${ln} ${fn}`;
// 既に生成した名前ならスキップして再抽選
if (generatedNames.has(fullName)) {
continue;
}
// 新しい名前なら採用して記録
generatedNames.add(fullName);
// 担当者名(こちらは重複してもOKとする)
const managerName = `${pick(lastNames)} ${pick(firstNames)}`;
const tel = `090-${String(randNum(0, 9999)).padStart(4, '0')}-${String(randNum(0, 9999)).padStart(4, '0')}`;
const pref = pick(prefectures);
const city = ["北区", "南区", "中央区", "港区", "新宿区", "渋谷区", "青葉区"][randNum(0, 6)];
records.push({
'顧客コード': { value: `CUST-${String(counter).padStart(5, '0')}` },
'顧客名': { value: fullName },
'顧客ランク': { value: pick(ranks) },
'郵便番号': { value: `${randNum(100, 999)}-${randNum(1000, 9999)}` },
'住所': { value: `${pref}${city} ${randNum(1, 9)}丁目${randNum(1, 20)}-${randNum(1, 20)}` },
'電話番号': { value: tel },
'メールアドレス': { value: `user${counter}@example.com` },
'担当者名': { value: managerName },
'締め日': { value: pick(closings) }
});
counter++;
}
console.log('Step 1: ユニークデータ生成完了。サーバーへの送信準備中...');
// --- 3. 100件ずつ分割して登録 ---
try {
const chunkSize = 100;
for (let i = 0; i < records.length; i += chunkSize) {
const chunk = records.slice(i, i + chunkSize);
const body = {
app: appId,
records: chunk
};
await kintone.api(kintone.api.url('/k/v1/records', true), 'POST', body);
console.log(`... ${Math.min(i + chunkSize, records.length)} / 1000 件 登録完了`);
}
console.log('-------------------------------------------------------');
console.log('🎉 レイ: 完了しました!');
console.log('1000件すべて異なる名前の顧客データが登録されました。');
console.log('-------------------------------------------------------');
} catch (error) {
console.error('🦊 レイ: エラーが発生しました。', error);
if (error.error) console.error(JSON.stringify(error.error, null, 2));
}
})();
- テストデータ生成結果
テストデータ生成作成手順
テストデータを生成して、問題を対策しながら調整していきます。
テストデータ生成1
最初はざっくりとした要件で
顧客マスタにテストデータ1000件を生成して
顧客名は、通番ではなく、日本名で妥当なものを
- 顧客名の重複が多い
- 文字検索プラグインを使って、顧客名で集計すると重複がわかる
テストデータ生成2
組合せを多くしてみた。
同姓同名のテストを考えると、ある程度重複を残した方がいいかも。
名前の重複が多いので、苗字と名前の数を増やして重複が少なくなるように
- これでも顧客名の重複が多い
テストデータ生成3
重複した顧客名を除外
まだ重複が多い。重複した顧客名を除外するようにして
- 重複なし







