0Pricing
C# Academy · บทเรียน

การแก้ไขข้อผิดพลาดของการทดสอบที่ล้มเหลว

ทำให้ความล้มเหลวเกิดซ้ำได้ ตัดเรื่องเวลาและการสุ่มออก ลดปัญหาให้เหลือกรณีเล็กที่สุด และปรับปรุงข้อความตรวจสอบผลเพื่อวินิจฉัยได้รวดเร็ว

การแก้ไขข้อผิดพลาดของการทดสอบที่ล้มเหลว เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C# Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C# Academy มีบทเรียนทั้งหมด 3 บทเรียน

แผนการแก้ไข

แผนสำหรับแก้ไขการทดสอบที่ล้มเหลว:

  • ทำให้เกิดซ้ำได้อย่างน่าเชื่อถือ
  • กำจัดความไม่เสถียร เช่น เวลาและการรับส่งข้อมูลแบบสุ่ม
  • ลดขนาดให้เหลือกรณีที่เล็กที่สุดซึ่งยังล้มเหลว
  • เพิ่มข้อความการยืนยันผลที่ชัดเจน

ไม่เสถียรตั้งแต่การออกแบบ

การใช้ UtcNow และ Random เริ่มต้นทำให้พฤติกรรมแตกต่างกันในแต่ละครั้งที่ทำงาน → การทดสอบจึงไม่เสถียร

using System;

// Demo: occasionally fails because it depends on current second and default Random()
public static class Promo
{
  // Gives bonus on even seconds; random adds small jitter
  public static int BonusNow()
  {
    int baseBonus = (DateTime.UtcNow.Second % 2 == 0) ? 10 : 9;
    Random r = new Random(); // time-based seed → unpredictable
    return baseBonus + (r.Next(0, 2)); // 0 or 1 more
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    // Simulated test: sometimes expects exactly 10, but result varies
    int got = Promo.BonusNow();
    if (got != 10) Console.WriteLine("FAIL (flaky): expected 10 but got " + got);
    else Console.WriteLine("PASS (maybe): got " + got);
  }
}

ควบคุมการพึ่งพา

ฉีดเวลาและ Random เมื่อใช้ seed ที่กำหนดตายตัวและเวลาประทับที่กำหนดตายตัว ความล้มเหลวจะทำซ้ำได้

using System;

public interface IClock { DateTime NowUtc(); }
public sealed class FakeClock : IClock
{
  private readonly DateTime _fixedUtc;
  public FakeClock(DateTime fixedUtc) { _fixedUtc = fixedUtc; }
  public DateTime NowUtc() { return _fixedUtc; }
}

public sealed class PromoDeterministic
{
  private readonly IClock _clock;
  private readonly Random _rng;
  public PromoDeterministic(IClock clock, Random rng) { _clock = clock; _rng = rng; }

  public int BonusNow()
  {
    int baseBonus = (_clock.NowUtc().Second % 2 == 0) ? 10 : 9;
    return baseBonus + _rng.Next(0, 2);
  }
}

public static class Assert
{
  public static void AreEqual(int expected, int actual, string msg)
  {
    if (expected != actual) throw new Exception("Expected " + expected + " but got " + actual + " :: " + msg);
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    try
    {
      IClock clock = new FakeClock(new DateTime(2016, 1, 1, 0, 0, 20, DateTimeKind.Utc)); // even second
      Random rng = new Random(123); // fixed seed
      PromoDeterministic p = new PromoDeterministic(clock, rng);

      int got = p.BonusNow(); // predictable now
      Assert.AreEqual(10, got, "even second, first draw should be 0");
      Console.WriteLine("PASS: deterministic promo");
    }
    catch (Exception ex)
    {
      Console.WriteLine("FAIL: " + ex.Message);
    }
  }
}

กรณีทำซ้ำขั้นต่ำ

ลดขนาดข้อมูลนำเข้าจนเหลือตัวอย่างเล็ก ๆ ที่ยังล้มเหลว ซึ่งในที่นี้คืออาร์เรย์ว่าง กรณีขนาดเล็กช่วยให้วิเคราะห์เหตุผลได้ง่ายกว่า

using System;

// Buggy function: average of ints, but divides by count without guarding empty input
public static class Stats
{
  public static double Average(int[] xs)
  {
    int sum = 0;
    for (int i = 0; i < xs.Length; i++) sum += xs[i];
    return sum / xs.Length; // BUG: divide by zero if empty; also int division truncates
  }
}

public static class Assert
{
  public static void Throws<T>(Action a, string msg) where T : Exception
  {
    try { a(); }
    catch (Exception ex)
    {
      if (ex is T) return;
      throw new Exception("Expected " + typeof(T).Name + " but got " + ex.GetType().Name + " :: " + msg);
    }
    throw new Exception("Expected " + typeof(T).Name + " but no exception thrown :: " + msg);
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    // Minimal failing case: empty array
    Assert.Throws<DivideByZeroException>(delegate { Stats.Average(new int[0]); }, "empty input");
    Console.WriteLine("Reproduced: empty input triggers the bug.");
  }
}

คุณภาพของการแก้ไขและข้อความ

ป้องกันข้อมูลนำเข้าที่ไม่ถูกต้อง และใช้ข้อความการยืนยันผลที่อธิบายได้ชัดเจน โดยระบุข้อมูลนำเข้า ค่าที่คาดหวัง และ epsilon

using System;

public static class Stats
{
  public static double Average(int[] xs)
  {
    if (xs == null) throw new ArgumentNullException("xs");
    if (xs.Length == 0) throw new ArgumentException("xs must not be empty", "xs");

    double sum = 0.0; // use double to avoid integer truncation
    for (int i = 0; i < xs.Length; i++) sum += xs[i];
    return sum / xs.Length;
  }
}

public static class Assert
{
  public static void AreAlmostEqual(double expected, double actual, double eps, string msg)
  {
    if (Math.Abs(expected - actual) > eps)
      throw new Exception("Expected " + expected + " but got " + actual + " (eps " + eps + ") :: " + msg);
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    try
    {
      double a = Stats.Average(new int[] { 2, 4, 6 });
      Assert.AreAlmostEqual(4.0, a, 1e-9, "average of 2,4,6");

      Console.WriteLine("PASS: fixed average with clear message");
    }
    catch (Exception ex)
    {
      Console.WriteLine("FAIL: " + ex.Message);
    }
  }
}

รายการตรวจสอบการแก้ไขข้อบกพร่อง

รายการตรวจสอบการแก้ไขข้อบกพร่อง:

  • ทำให้การพึ่งพามีความคงที่ เช่น เวลา ค่าสุ่ม และการรับส่งข้อมูล
  • ทำซ้ำในเครื่องและทำซ้ำหลายครั้ง
  • ลดขนาดให้เหลือข้อมูลนำเข้าขั้นต่ำที่ยังล้มเหลว
  • เพิ่มข้อความการยืนยันผลที่แม่นยำ
  • ควรใช้ฟังก์ชันบริสุทธิ์และการตรวจสอบป้องกัน

ขั้นตอนแรกสำหรับการทดสอบที่ไม่เสถียร

ตรวจสอบอย่างรวดเร็ว: การทดสอบที่ล้มเหลวเป็นบางครั้งใช้ DateTime.UtcNow และ new Random() ขั้นตอนแรกที่ดีที่สุดคืออะไร

สรุป

สรุป: ทำให้เกิดซ้ำได้อย่างน่าเชื่อถือโดยควบคุมเวลาและความสุ่ม ลดขนาดข้อมูลนำเข้า และเขียนข้อความการยืนยันผลที่ช่วยระบุตำแหน่งข้อบกพร่องได้อย่างรวดเร็ว

คำถามที่พบบ่อย

บทเรียน “การแก้ไขข้อผิดพลาดของการทดสอบที่ล้มเหลว” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การแก้ไขข้อผิดพลาดของการทดสอบที่ล้มเหลว” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 3 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การแก้ไขข้อผิดพลาดของการทดสอบที่ล้มเหลว”

ทำให้ความล้มเหลวเกิดซ้ำได้ ตัดเรื่องเวลาและการสุ่มออก ลดปัญหาให้เหลือกรณีเล็กที่สุด และปรับปรุงข้อความตรวจสอบผลเพื่อวินิจฉัยได้รวดเร็ว คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 3 บทเรียน

บทเรียน “การแก้ไขข้อผิดพลาดของการทดสอบที่ล้มเหลว” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม

ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การตั้งค่า xUnit/MSTest และการตรวจสอบผล
  2. ตัวจำลองผ่านอินเทอร์เฟซและตัวสร้างข้อมูลทดสอบ
  3. การแก้ไขข้อผิดพลาดของการทดสอบที่ล้มเหลว
← กลับไปที่ C# Academy