Saya mencoba menguji fungsi yang sangat sederhana. Ini mengembalikan angka yang berisi beberapa digit tertentu. Jika argumen pertama adalah null, itu akan melempar ArgumentNullException.

Sayangnya, Assert.Throws mengatakan, bahwa pengecualian yang diharapkan tidak dilempar dan pengujian gagal. Ketika saya mencoba untuk men-debug tes, itu tidak masuk ke metode saya. Hal yang sama dengan ArgumentException.

Hanya dua tes terakhir yang gagal, yang lain berhasil.

Fungsi saya yang akan diuji:

    /// <summary>
    /// Filter given numbers and return only numbers containing the specified digit.
    /// </summary>
    /// <param name="numbers">The numbers to be filtered.</param>
    /// <param name="digit">The digit which should be found.</param>
    /// <returns>Numbers that contains the digit.</returns>
    /// <exception cref="ArgumentException"> Thrown if the digit value isn't between 0 and 9.</exception>
    /// <exception cref="ArgumentNullException"> Thrown if numbers are null.</exception>
    public static IEnumerable<int> FilterDigits(IEnumerable<int> numbers, byte digit)
    {
        if (numbers == null)
        {
            throw new ArgumentNullException();
        }

        foreach (int number in numbers)
        {
            if (number.ContainsDigit(digit))
            {
                yield return number;
            }
        }
    }

    /// <summary>
    /// Check whether the number contains the given digit.
    /// </summary>
    /// <param name="number">The number which can contain the digit.</param>
    /// <param name="digit">The digit to be found.</param>
    /// <returns>True if the number contains the digit, else false.</returns>
    /// <exception cref="ArgumentException"> Thrown if the digit value isn't between 0 and 9.</exception>
    /// <example> ContainsDigit(10, 1) -> true </example>
    /// <example> ContainsDigit(10, 2) -> false </example>
    private static bool ContainsDigit(this int number, byte digit)
    {
        if (!char.TryParse(digit.ToString(), out char digitChar))
        {
            throw new ArgumentException("The digit should be from 0 to 9.");
        }

        string numberString = number.ToString();

        foreach (char ch in numberString)
        {
            if (ch == digitChar)
            {
                return true;
            }
        }

        return false;
    }

Kelas tes saya:

[TestFixture]
public class DigitsFilterTests
{
    [TestCase(new int[] { 1, 4, 23, 346, 7, 23, 87, 71, 77 }, 7, ExpectedResult = new int[] { 7, 87, 71, 77 })]
    [TestCase(new int[] { 345, 4, 0, 90, 709 }, 0, ExpectedResult = new int[] { 0, 90, 709})]
    public IEnumerable<int> FilterDigits_NumbersContainDigit(int[] numbers, byte digit)
        => DigitsFilter.FilterDigits(numbers, digit);

    [TestCase(new int[] { 1, 4, 222, 9302 }, 7, ExpectedResult = new int[] { })]
    [TestCase(new int[] { 345, 4, 354, 25, 5 }, 0, ExpectedResult = new int[] { })]
    public IEnumerable<int> FilterDigits_NumbersNotContainDigit(int[] numbers, byte digit)
        => DigitsFilter.FilterDigits(numbers, digit);

    [TestCase(new int[] { }, 0, ExpectedResult = new int[] { })]
    public IEnumerable<int> FilterDigits_EmptyList(int[] numbers, byte digit)
        => DigitsFilter.FilterDigits(numbers, digit);

    [Test]
    public void FilterDigits_NullNumbers_ArgumentNullException()
        => Assert.Throws<ArgumentNullException>(() => DigitsFilter.FilterDigits(null, 5));

    [Test]
    public void FilterDigits_InvalidDigit_ArgumentException()
        => Assert.Throws<ArgumentException>(() => DigitsFilter.FilterDigits(new int[] { }, 10));
}
7
Karalina Dubitskaya 23 Maret 2019, 22:38

1 menjawab

Jawaban Terbaik

Metode Anda adalah enumerable yang dibuat menggunakan yield return. Yang rumit adalah tidak ada yang benar-benar akan terjadi kecuali Anda menghitungnya.

Jadi, Anda harus memastikan bahwa pengujian Anda menghitung konten:

    [Test]
    public void FilterDigits_NullNumbers_ArgumentNullException()
        => Assert.Throws<ArgumentNullException>(() => DigitsFilter.FilterDigits(null, 5).ToList());

Selain itu, pengujian kedua Anda akan gagal karena Anda tidak akan mencapai ContainsDigit jika numbers kosong.

Jika Anda ingin memperbaiki perilaku di dalam metode, Anda perlu memotongnya menjadi dua:

public static IEnumerable<int> FilterDigits(IEnumerable<int> numbers, byte digit)
{
    if (numbers == null)
    {
        throw new ArgumentNullException();
    }

    return FilterDigitsImpl(numbers, digit);
}

private static IEnumerable<int> FilterDigitsImpl(IEnumerable<int> numbers, byte digit)
{
    foreach (int number in numbers)
    {
        if (number.ContainsDigit(digit))
        {
            yield return number;
        }
    }
}

Jika versi C# Anda cukup baru, Anda dapat menggabungkan kedua metode menggunakan fungsi lokal:

public static IEnumerable<int> FilterDigits(IEnumerable<int> numbers, byte digit)
{
    if (numbers == null)
    {
        throw new ArgumentNullException();
    }

    IEnumerable<int> FilterDigitsImpl()
    {
        foreach (int number in numbers)
        {
            if (number.ContainsDigit(digit))
            {
                yield return number;
            }
        }
    }

    return FilterDigitsImpl();
}
6
Kevin Gosse 23 Maret 2019, 19:55