Apexにおける @TestVisible の活用方法とコードカバー率の計算


# **1. `@TestVisible` の活用方法とメリット**  
### **1.1 `@TestVisible` とは？**
通常、`private` なメソッドや変数はクラス外部からアクセスできません。しかし、Apex ではユニットテストで `private` なメソッドや変数にアクセスする必要がある場合があります。  

そこで **`@TestVisible` を使うと、`private` な変数やメソッドをテストクラスから参照できる** ようになります。

---

## **1.2 `@TestVisible` の基本的な使い方**
### **✅ `@TestVisible` を変数に適用する例**
```apex
public class PokemonManager {
    @TestVisible private static Integer pokemonCount = 0;

    public static void addPokemon() {
        pokemonCount++;
    }

    public static Integer getPokemonCount() {
        return pokemonCount;
    }
}
```
**このクラスのテストコード**
```apex
@isTest
private class PokemonManagerTest {
    @isTest
    static void testPokemonCount() {
        // `pokemonCount` に直接アクセス可能
        System.assertEquals(0, PokemonManager.pokemonCount);

        PokemonManager.addPokemon();
        System.assertEquals(1, PokemonManager.pokemonCount);
    }
}
```
> **ポイント:**  
> - `pokemonCount` は `private` だが、`@TestVisible` によってテストコードからアクセス可能  
> - ユニットテストで `pokemonCount` の変化を検証できる  

---

### **✅ `@TestVisible` をメソッドに適用する例**
```apex
public class PokemonTrainer {
    @TestVisible private static Boolean hasRarePokemon(String pokemonName) {
        return pokemonName == 'Mew' || pokemonName == 'Rayquaza';
    }

    public static String checkPokemon(String pokemonName) {
        if (hasRarePokemon(pokemonName)) {
            return pokemonName + ' is a rare Pokémon!';
        }
        return pokemonName + ' is a common Pokémon.';
    }
}
```
**このクラスのテストコード**
```apex
@isTest
private class PokemonTrainerTest {
    @isTest
    static void testHasRarePokemon() {
        // `hasRarePokemon` は private だが、テストで直接呼び出し可能
        System.assert(PokemonTrainer.hasRarePokemon('Mew'));
        System.assert(!PokemonTrainer.hasRarePokemon('Pikachu'));
    }
}
```
> **ポイント:**  
> - `hasRarePokemon` は `private` メソッドだが、`@TestVisible` によってテストから直接検証可能  
> - 本来 `public` にしたくないが、テスト時のみ参照したいときに便利  

---

### **1.3 `@TestVisible` のメリット**
✅ **本番環境のカプセル化を保つ**（`private` のままにできる）  
✅ **テストコードから `private` な変数・メソッドを検証できる**  
✅ **デバッグやテスト時に特定の内部値をチェックできる**  

**⚠ 注意点:**  
`@TestVisible` をつけると **すべてのテストクラスからアクセス可能** になるため、**本当に必要な場合のみ使用する** ようにしましょう。  

---

# **2. Apex のコードカバー率の計算方法**
### **2.1 コードカバー率とは？**
Apex の **コードカバー率（Code Coverage）** とは、**実際にテストで実行されたコードの割合** を指します。  
Salesforce では、本番環境にデプロイするには **全体のコードカバー率が 75%以上** である必要があります。

---

## **2.2 コードカバー率の計算方法**
コードカバー率の計算式は以下の通り：
```
コードカバー率 = (実行されたコード行数 ÷ 全コード行数) × 100%
```
たとえば：
- **クラスの総行数**: `10` 行
- **テストで実行された行数**: `8` 行
- **コードカバー率**: `(8 ÷ 10) × 100 = 80%`

---

## **2.3 コードカバー率の確認方法**
### **✅ Salesforce Developer Console を使用する方法**
1. **[開発者コンソール]** → **[Test] → [New Run]** を開く  
2. テスト対象のクラスを選択して実行  
3. **[Test] → [View Code Coverage]** で確認  
4. カバーされているコードは青、カバーされていないコードは赤で表示される  

---

## **2.4 コードカバー率を上げる方法**
### **✅ カバーされていないコードを特定する**
- **条件分岐（if, else, try-catch）** のパターンをすべて網羅  
- `System.assert()` で **期待する動作を検証**  
- `Test.startTest()` / `Test.stopTest()` を活用し **バッチやフローの処理を確実に実行**  

---

## **2.5 コードカバー率を考慮したテストコード**
**対象クラス**
```apex
public class PokemonService {
    public static String getPokemonType(String name) {
        if (name == 'Pikachu') {
            return 'Electric';
        } else if (name == 'Charmander') {
            return 'Fire';
        } else {
            return 'Unknown';
        }
    }
}
```
**NG テスト（コードカバー率 67%）**
```apex
@isTest
private class PokemonServiceTest {
    @isTest
    static void testGetPokemonType() {
        System.assertEquals('Electric', PokemonService.getPokemonType('Pikachu'));
        System.assertEquals('Fire', PokemonService.getPokemonType('Charmander'));
    }
}
```
> **⚠ 問題点:**  
> - `else` のパターン (`Unknown`) がカバーされていない → **カバー率 67%**

---

**OK テスト（コードカバー率 100%）**
```apex
@isTest
private class PokemonServiceTest {
    @isTest
    static void testGetPokemonType() {
        System.assertEquals('Electric', PokemonService.getPokemonType('Pikachu'));
        System.assertEquals('Fire', PokemonService.getPokemonType('Charmander'));
        System.assertEquals('Unknown', PokemonService.getPokemonType('Bulbasaur')); // else 分岐をカバー
    }
}
```
> **✅ `else` もカバーし、コードカバー率 100% に！**

---

# **まとめ**
✅ **`@TestVisible` を活用すると `private` な変数・メソッドをテストできる**  
✅ **コードカバー率は 75%以上が必須（未実行のコードを減らすことが重要）**  
✅ **テストケースを増やし、条件分岐をすべて網羅するとカバー率が上がる**  

**テストの品質を向上させ、バグのない Apex コードを目指しましょう！🚀**