【问题标题】:How do I make a unit test out of my code in C#如何在 C# 中使用我的代码进行单元测试
【发布时间】:2019-11-22 23:08:17
【问题描述】:

所以我正在做一个简单的扑克测试,我必须显示玩家的姓名和他们的手牌,手牌高的玩家获胜。对于这个测试,没有花色和等级(例如黑桃 10、方块 J),只有玩家应该拥有的手牌类型(例如皇家同花顺、顺子、高牌等)。输出应该是这样的:

Player 1, Jane's hand is: Full House
Player 2, John's hand is: One Pair
Winner: Jane (Full House)

现在,我已经掌握了所有的逻辑(您将在下面看到)。但是,我现在应该为此进行单元测试。我看过一些教程,但是如果您在下面看到我的代码,我认为它不适合单元测试。如果有人可以帮助我修复我的单元测试代码,我非常感谢。

代码如下:

public class PokerGame
{
    static void Main(string[] args)
    {
        // Names of the players
        string player1Name, player2Name;

        // The array of the poker hands
        string[] pokerHands =
        {
            "High Card", "One Pair", "Two Pair", "Three of a Kind", "Straight", "Flush",
            "Full House", "Four of a Kind", "Straight Flush", "Royal Flush"
        };

        // This will prompt the players to type their name
        Console.Write("Enter Player 1: ");
        player1Name = Console.ReadLine();
        Console.Write("Enter Player 2: ");
        player2Name = Console.ReadLine();

        // This Random object will deal random hands accordingly
        Random randomHand = new Random();

        // The random hand index assigned to Player 1
        int hand1 = randomHand.Next(pokerHands.Length);

        // The random hand index assigned to Player 2
        int hand2 = randomHand.Next(pokerHands.Length);

        Console.WriteLine("Player 1, " + player1Name + "'s, hand is: " + pokerHands[hand1]);
        Console.WriteLine("Player 2, " + player2Name + "'s, hand is: " + pokerHands[hand2]);

        // If the random hand index for Player 1 is greater than that for Player 2
        if (hand1 > hand2)
        {
            // Then Player 1 wins
            Console.WriteLine("Winner: " + player1Name + " (" + pokerHands[hand1] + ").");
        }
        // But if it's the opposite
        else if (hand1 < hand2)
        {
            // Player 2 wins
            Console.WriteLine("Winner: " + player2Name + " (" + pokerHands[hand2] + ").");
        }
        // And if they have the same hands
        else
        {
            Console.WriteLine("It's a tie!");
        }

        Console.ReadLine();
    }
}

编辑:在得到一些朋友和 Facebook 上的人的帮助后 (LOL),我设法将我的一些代码重构为:

public class PokerDealer
    {
        string[] hands =
            {
                "High Card", "One Pair", "Two Pair", "Three of a Kind", "Straight", "Flush",
                "Full House", "Four of a Kind", "Straight Flush", "Royal Flush"
            };

        public void DealCards(int hand1, int hand2, string name1, string name2)
        {
            Random randomHand = new Random();

            hand1 = randomHand.Next(hands.Length);
            hand2 = randomHand.Next(hands.Length);

            Console.WriteLine("Player 1, " + name1 + "'s hand: " + hands[hand1]);
            Console.WriteLine("Player 2, " + name2 + "'s hand: " + hands[hand2]);

            CheckWinner(hand1, hand2, name1, name2);
        }

        public int CheckWinner(int win1, int win2, string name1, string name2)
        {
            int winner;

            if (win1 > win2)
            {
                winner = win1;
                Console.WriteLine("Winner: " + name1 + " (" + hands[winner] + ")");
            }
            else if (win1 < win2)
            {
                winner = win2;
                Console.WriteLine("Winner: " + name2 + " (" + hands[winner] + ")");
            }
            else
            {
                winner = 0;
                Console.WriteLine("It's a tie!");
            }

            return winner;
        }
    }

DealCards() 基本上是我的随机数生成器(发出随机牌),而 CheckWinner() 则检查谁有获胜牌。另外,我已经对两个玩家的获胜条件进行了单元测试,并且它们有效!现在这里有一些问题:

  1. 我现在将如何测试他们是否拥有相同的卡? (最后一个条件)
  2. 我正在尝试对 DealCards() 进行测试,以查看玩家是否确实获得了随机牌,并查看它是否超出范围(0 到 9;可能更重要)。对于这个,我不知道我将如何断言后一种条件。测试方法如下:
        [TestMethod]
        public void RandomHand()
        {
            // Tests if players are given a random hand within the range
            PokerDealer pd = new PokerDealer();
            Random randomHand = new Random();

            int randomHandIndex = randomHand.Next(10);
            pd.DealCards(randomHandIndex, randomHandIndex, "Player 1", "Player 2");
        }

【问题讨论】:

  • 确实不是,你需要一些单位。基本上将您的代码从 Main 移动到一些类中,然后测试它们中的每一个。例如 Hand、Player、Winner 和 Game 的类
  • @TonyHopkinson 所以只是单独上课?因为根据我的理解,我应该在单元测试中测试方法,对吧?如果我错了,请纠正我。
  • 如果你练习 TDD,编写单元测试会更容易,而不是先写一堆代码,然后再考虑测试
  • @MiguelLorenzoPagkatipunan,“它不适合单元测试”。你明白了。尽量将它们转换成小而纯的碎片。通过练习 TDD,auburg 想说,在开发这段代码的同时练习 TDD
  • 即使不使用 TDD,也应该编写可以进行单元测试的代码。使用 SOLID 即可。

标签: c# unit-testing


【解决方案1】:

为了使代码更适合单元测试,我的建议是:只有 Main() 方法应该通过 Console.Write() 打印文本。所有其他方法应该只返回值。这样,您的测试可以调用方法并检查您对返回值的假设。例如,CheckWinner() 应该将它当前写入的文本返回到控制台,以便您可以在测试中验证 CheckWinner() 返回的字符串(可能重命名为 GetResultText() 或其他东西)匹配输入参数。

至于测试某些场景,例如两个玩家拥有同一手牌,有两种选择:

  • 为 Random 创建一个模型。这样,您可以控制在单元测试中使用时它返回的值。这是一个高级主题,但它是一种非常有用的单元测试技术。 Google C# 模拟。
  • 每次对随机实例使用相同的种子(当然只有在测试时!);这样,Next() 调用返回的值将始终相同,您可以将它们用于测试。例如

    Random r = new Random(9);
    Console.WriteLine(r.Next(10));
    Console.WriteLine(r.Next(10));
    

将连续给您两个四人组 - 每次。

至于最后一点,如何测试ranodm 是否返回给定范围内的随机数。为什么要这么做?随机它不是您代码的一部分,因此您对其进行测试没有意义。

【讨论】:

  • 感谢您的回答,虽然我不确定如何删除 CheckWinner() 中的 Console.Write() 部分b> 和 DealCards()。我这样做是因为我在 Main() 方法中实现了输入玩家名称,但是当我运行 DealCards() 时名称消失了。我希望我说得通,哈哈。
猜你喜欢
  • 2019-08-25
  • 1970-01-01
  • 1970-01-01
  • 2012-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-03
相关资源
最近更新 更多