Visual Basic

例外処理とテスト

失敗の原因を読み、想定内の失敗へ対応し、正しい結果を自動で確認しましょう。

01

例外名と発生行を読む

エラーが起きたら、例外の種類、説明、自分のファイル名と行番号を確認します。次の例では、要素が2個なので位置2は存在しません。

エラーになる例VISUAL BASIC
Dim prices() As Integer = {100, 200}
Console.WriteLine(prices(2))
表示の要点OUTPUT
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at Program.Main(...) in Program.vb:line 3
02

想定できる失敗を処理する

Catchには対応できる具体的な例外型を書き、Finallyには成功・失敗にかかわらず必要な後処理を書きます。

設定ファイルを読むVISUAL BASIC
Try
    Console.WriteLine(File.ReadAllText("settings.txt"))
Catch ex As FileNotFoundException
    Console.WriteLine("設定ファイルがありません")
Catch ex As UnauthorizedAccessException
    Console.WriteLine("ファイルを読む権限がありません")
Finally
    Console.WriteLine("読み込み処理を終了します")
End Try
何でも無視しない Catch ex As Exceptionだけで全てを捕捉して何もしないと、プログラムの誤りまで隠れます。対応できない例外は記録するか、呼び出し元へ伝えます。
03

不正な値をThrowで知らせる

値を検証するVISUAL BASIC
Function CalculateTotal(price As Integer, count As Integer) As Integer
    If price < 0 Then Throw New ArgumentOutOfRangeException(NameOf(price))
    If count < 1 Then Throw New ArgumentOutOfRangeException(NameOf(count))
    Return price * count
End Function

引数の範囲違反にはArgumentOutOfRangeExceptionのように意味の合う型を選びます。利用者の入力ミスは通常の分岐で再入力を促すなど、例外と通常状態を区別しましょう。

04

表示と計算を分ける

入力・表示から計算を分離し、引数と戻り値だけで動く関数にするとテストしやすくなります。

DiscountCalculator.vbVISUAL BASIC
Public Class DiscountCalculator
    Public Shared Function Apply(price As Integer, rate As Integer) As Integer
        If price < 0 Then Throw New ArgumentOutOfRangeException(NameOf(price))
        If rate < 0 OrElse rate > 100 Then
            Throw New ArgumentOutOfRangeException(NameOf(rate))
        End If
        Return price * (100 - rate) \ 100
    End Function
End Class
05

MSTestで自動テストする

ソリューションの隣にVisual Basicのテストプロジェクトを作り、対象プロジェクトを参照します。

テスト準備と実行COMMAND
dotnet new mstest -lang VB -o Shop.Tests
dotnet add Shop.Tests reference Shop
dotnet test
DiscountCalculatorTests.vbVISUAL BASIC
<TestClass>
Public Class DiscountCalculatorTests
    <TestMethod>
    Public Sub Apply_1000円を10パーセント引き_900円になる()
        Assert.AreEqual(900, DiscountCalculator.Apply(1000, 10))
    End Sub

    <TestMethod>
    Public Sub Apply_割引率が101_例外になる()
        Assert.ThrowsException(Of ArgumentOutOfRangeException)(
            Sub() DiscountCalculator.Apply(1000, 101))
    End Sub
End Class
成功時の要点OUTPUT
合計テスト数: 2
     成功: 2
合計時間: ...

出力の文言はSDKや表示言語で異なりますが、失敗数が0であることを確認します。

PRACTICE

ミニ課題:送料計算のテスト

購入金額が3000円以上なら送料無料、それ未満なら500円、負の金額は例外とする関数を作ります。2999、3000、負の値という境界をテストしてください。