[Salesforce] Sandbox環境へデータを取り込む時はSandboxberryを使ってみよう

# イントロ

Apex開発で一番面倒くさかったのはテストデータを用意することでした。


ある時は最低６個以上のカスタムオブジェクトを手作りして、
そのオブジェクトは複数の参照関係を持っていて、
さらに処理自体もかなりの複雑さを誇るものでSOQLもバンバン呼んでいて。


当然ガバナー制限に影響を受けるか否かも確かめないといけないですね。
そのテストのために1オブジェクト200レコード以上要るものですから、単純に計算しても
1200件のテスト用データを用意することになってしまったという悲劇に遭遇したことがあります。


そこから思考は”この闇深すぎるなー” → ”これSalesforceの開発する人なら誰もがこの闇感じるな絶対” → ”有償でもいいから何か良い自動化ツールないのか”でした。
運よく、すぐ**Sandboxberry**を見つけまして、2時間後は50万弱のテスト用データをStaging環境に入れることができました。 


下にも説明しますが、Salesforce開発においてテスト＋データ移行は嫌な作業になりがちですので、
このツールはかなり便利ものだと思い、是非紹介させて頂きたいと思いました。


＊ 　日本に働く外国人エンジニアです。”何言ってんだこいつ”的なところが結構多いと思いますが、大目に見て頂ければ幸いです。
＊＊ 下の説明の大半は [ここ](https://github.com/codeulike/SandboxBerry/wiki)の内容をベースにしています。 

# Sandboxberryとは？

Salesforce環境の間で**テスト用データの移行**を簡単にしてくれるオープンソースツールです。[こちら](https://github.com/codeulike/SandboxBerry/releases)で入手できます。（Windowsのみ / .NET 4.5＋必須）

# なぜ使うのか？（どういう時に使いたいのか？）

本番環境から新しくサンドボックス環境を作ると、一部タイプを除いたSandbox環境はデータが入っていないクリーンな状態で作られます。
そのSandboxで新しい機能を開発したり、既存機能を修正するとしても、結局本番環境にデプロイする前にテストしなければいけません。
しかし、テスト用データも用意されていない為、直接作るか、他の環境から既存データをインポートするしかありません。

簡単なものであれば、SOQLやGUIでデータを生成しても問題ないですが、実業務ではテストデータの準備自体が結構大変です。主に：

* 複数のsObjectが必要で、多数の依存関係もしくはハイアラーキーが存在　AND/OR
* 複数のsObjectを絡む処理に多数のパターンが存在。パターンごとのデータを用意する必要あり AND/OR
* 本番と同じデータでテストを行いたい AND/OR
* ガバナー制限に引っかかるか確認する為、多量のデータを要する

などのケースが思い浮かびます。 

こういう時、一番”簡単”な方法は Data Loader等のETLツールを利用して本番や他Sandbox環境のデータをコピーして取り込むことなんですが、
この方法は１００回中９０回は失敗してしまいます。その理由としては：

* 他の環境にレコードを移行する時、そのレコードのIDが変わってしまう。よって、他sObjectとの参照関係が存在するレコードはその参照関係を保つことができない。  
* 片方の環境だけ項目の変更がある場合、項目のずれでインポート作業が失敗する。
* レコードの所有者が何らかの理由で無効化された時、もしくは本番には存在するけどSandboxに存在しないユーザーが所有者となっている時、インポート作業が失敗する。

Sandboxberryはこういう問題に自動で対応してくれるので、sObjectが複数あるとしてもすごく簡単に、効率よくインポートできます。

# 何がすごいのか？

* 取込対象sObjectが複数あって参照関係が存在する場合、参照関係を保存しつつ取り込むことができます。 
  * 例）sObjectのAとBは参照関係を持つ。この２つのsObjectを他組織に移行する。 
    * （既存）1. Aを移行する。===> 2. Bを移行する。 ===> 3. A(or B)の外部ID項目をData Loader などで更新する。 ===> Done.
    * （SandboxBerry) 1. AとBを更新する。 ===> Done.

* 取込先組織と元組織、両方に存在する項目のみデータ移行します。指定した項目を除いて移行することもできます。

* 無効化されたユーザーが所有者であるレコードも移行可能です。

この３つがデータ移行時に頻繁に発生するpain pointですので、大変うれしいですね。

# 使ってみましょう

1. [ここ](https://github.com/codeulike/SandboxBerry/releases)で最新版（作成時点は1.3.0.0)をダウンロードします。
2. 圧縮を展開して、Sandboxberry.exeを実行します。  
3. ![image.png](https://qiita-image-store.s3.amazonaws.com/0/190619/a83ee3ec-841a-d6d6-6ee8-d33cc01d5760.png)

3. Source側（左）の"LoginUrl"でインポート元がProduction環境かSandbox環境かを選択します。Target側（右）は必ずSandbox環境です。その理由は下の注意事項をご参照ください。
4. 各環境のログイン情報を入力します。
5. 次はInstructions Fileですが、#2で展開したフォルダー内のExampleInstructionFilesフォルダーのExampleInstructionFile1.xmlをコピーします。
6. 移行したいsObjectの名称を次のようにApi名を登録します。  

```xml

<!-- １．全レコードを取得 -->
<SbbObject ApiName="hoge__c" /> 
<!-- ２．WHERE句の条件に一致するレコードのみ取得 --> 
<SbbObject ApiName="hoge__c" Filter="hogefield__c = 'hello'" /> 

<SbbObject ApiName="hoge__c">
  <SbbFieldOptions>
    <!-- ３．値を一律的に登録　-->
	<SbbFieldOption ApiName="Email__c" ReplaceText="example@test.com" />	
    <!-- ４．取込をスキップする項目を指定 -->
    <SbbFieldOption ApiName="Work_Phone__c" Skip="true" />
  </SbbFieldOptions>
</SbbObject>
```

_7. Sandboxberryプログラムに戻り、 Instruction Filesに#5でコピーしたファイルを設定します。
8. Startを押してしばらく待つと完了です。（実行中はLogファイルにプロセスが書き込まれます）

# 注意) 登録したいsObjectが複数 + 依存関係が存在するケースについて  
一番重要なのは**sObject間の関係に沿って順番に登録すること**です。  
例えば、A, B, C というオブジェクトがあるとします。  
CがAの子オブジェクトでCがBを参照する関係の場合、正しい順番は以下になります：

```xml

<SbbObject ApiName="B__c" />  <!-- C生成時点でBのIDが必要 -->
<SbbObject ApiName="A__c" />  <!-- C生成時点でAのIDが必要 -->
<SbbObject ApiName="C__c" />　
```

また、注意事項があります： 

- **1回の実行に参照関係があるオブジェクトを全部まとめること**
  - 例） A, B, C, D というオブジェクトがあります。BとCはAを参照します。Dはどのオブジェクトとも参照関係がありません。
    - OKケース　→　1回目の実施：A, B, C // 2回目の実施：D 
    - NGケース　→　1回目の実施：A, B　// 2回目の実施：C, D
      - NGの理由： 2回目実行時のCはAの外部キーが分からないため
- **取込先の対象テーブルにレコードが存在しないこと**
  - Sandboxberryはxmlファイルで指定したsObjectのデータのみ取込先環境から削除する機能がありますので、それを使ってください。
  - Sandboxberry起動 → ツールバー　→　Tools ->　Clear Target Data 
   
# その他注意事項

* 移行先は必ずSandbox環境になります。あくまでプロセスの用途としてテスト用データの移行のために作られたプログラムですので、ご了承を。
* テストデータの移行を目的としているので、所有者が無効化されたレコードを移行する場合等、移行データの一部項目がプログラム側で書き換わってしまうケースがあります。
* 自分自身を参照（Self-lookup)するオブジェクトも移行可能ですが、1オブジェクトに1個まで認識可能ですのでご注意ください。