我有一个使用SOLID原理和TDD的小型C#技术任务。但是我无法通过测试证明自己的编码技能。

谁能为我提供一些小建议?我真的很想知道我的缺点是什么以及我该如何改善。

面试问题在这里,我的答案在这里。

我只在这里引用一些内容我的源代码。

Program.cs

class Program
{
    static void Main(string[] args)
    {

        ////////////////////////////////////////////////////////////////////////////////
        // Story 1. As a donor
        Console.WriteLine("-------------------------------------- Story1\r\n");

        //1.1. Craete Tax Calculator
        decimal taxRate = 20;
        ITaxCalculator taxCalculator = new TaxCalculator(taxRate);

        //1.2. Display GiftAid
        Console.WriteLine("Please enter donation amount:");
        decimal Amount = decimal.Parse(Console.ReadLine());
        Console.WriteLine("=> Your Gift Aid is: {0} \r\n\r\n", taxCalculator.GetGiftAid(Amount));

        ////////////////////////////////////////////////////////////////////////////////
        // Story 2. As a site administrator
        Console.WriteLine("-------------------------------------- Story2\r\n");

        //2.1. Create using factory pattern
        taxCalculator = new TaxCalculatorFactory().GetObject(new TaxRepository());

        Console.WriteLine("Please enter donation amount:");
        Amount = decimal.Parse(Console.ReadLine());

        //2.2. Display GiftAid
        Console.WriteLine("=> Your Gift Aid is: {0} \r\n\r\n", taxCalculator.GetGiftAid(Amount));


        Console.WriteLine("Press any key to exit.");
        Console.ReadLine();
    }
}


计算器类

interface ITaxCalculatorFactory
{
    ITaxCalculator GetObject(decimal taxRate);
    ITaxCalculator GetObject(ITaxRepository taxRepo);
}

public class TaxCalculatorFactory
{
    public TaxCalculatorFactory()
    {
    }
    public ITaxCalculator GetObject(decimal dAmount)
    {
        return new TaxCalculator(dAmount);
    }
    public ITaxCalculator GetObject(ITaxRepository taxRepo)
    {
        return new TaxCalculatorByData(taxRepo);
    }
}


public interface ITaxCalculator
{
    decimal GetGiftAid(decimal dAmount);
}

public class TaxCalculator : ITaxCalculator
{
    private readonly decimal _taxRate;
    public TaxCalculator(decimal taxRate)
    {
        _taxRate = taxRate;
    }

    public decimal GetGiftAid(decimal dAmount)
    {
        var gaRatio = _taxRate / (100 - _taxRate);
        return dAmount * gaRatio;
    }

}

public class TaxCalculatorByData : ITaxCalculator
{
    private readonly ITaxRepository _taxRepo;
    public TaxCalculatorByData(ITaxRepository taxRepo)
    {
        _taxRepo = taxRepo;
    }

    public decimal GetGiftAid(decimal dAmount)
    {
        var gaRatio = _taxRepo.GetTaxRate() / (100 - _taxRepo.GetTaxRate());
        return dAmount * gaRatio;
    }

}


/>测试代码

[TestFixture]
public class GetAidTest
{
    ////////////////////////////////////////////////////////////////////////////////
    // Story 1. As a donor
    [Test]
    public void Story1_Should_Return_TwentyFive_From_GiftAid()
    {
        /////////////////////////////////////////////////////////////
        // Setup
        decimal taxRate = 20;
        decimal donationAmount = 100;
        decimal valueExpected = 25;
        var taxCalculator = new TaxCalculator(taxRate);

        /////////////////////////////////////////////////////////////
        // Action
        var result = taxCalculator.GetGiftAid(donationAmount);

        /////////////////////////////////////////////////////////////
        // Verify the result
        Assert.AreEqual(valueExpected, result, "Should return 25");
    }

    ////////////////////////////////////////////////////////////////////////////////
    // Story 2. As a administrator
    [Test]
    public void Story2_Should_Store_TaxRate_Fourty_And_Return_GiftAid()
    {

        /////////////////////////////////////////////////////////////
        // Setup
        decimal taxRate = 40;
        decimal donationAmount = 100;
        decimal valueExpected = 66.67m;

        var repository = new Mock<ITaxRepository>();

        repository.Setup(r => r.GetTaxRate()).Returns(taxRate);
        repository.Setup(r => r.Save(It.IsAny<decimal>())).Verifiable();

        ITaxCalculator taxCalculator = new TaxCalculatorFactory().GetObject(repository.Object);

        /////////////////////////////////////////////////////////////
        // Action
        var result = decimal.Round(taxCalculator.GetGiftAid(donationAmount), 2, MidpointRounding.AwayFromZero);

        /////////////////////////////////////////////////////////////
        // Verify the result
        Assert.AreEqual(valueExpected, result, "Should return 25");
    }
}


评论

您是否从公共仓库提交了拉取请求? “如果您有一个付费的GitHub帐户,请随时创建一个私人仓库...并向我们发送请求请求。” [他们的重点]

“这项作业平均需要30分钟左右。” 30分钟内有4个用户故事。他们必须有非常好的程序员。

#1 楼


访谈定义了4个用户案例,但据我所知,您实际上只实现了2个。
故事3表示,该数量应四舍五入到小数点后两位。您可以通过将舍入作为结果(作为单元测试的一部分)对结果进行舍入来完成,而单元测试会遗漏故事的重点(恕我直言)。这个故事说了一些有关“应该四舍五入到小数点后两位”的内容,因此它可能需要一个税务计算器视图,该视图根据要求显示结果。
您应该避免使用两种方法来创建TaxCalculator对象。如果您有工厂,那么通常不希望用户通过new实例化新对象。如果我要使用您的班级,我将不知道该使用哪种方法,以及是否存在差异。 br />在工厂中,我希望使用dAmount而不是Create作为方法名称。
删除GetObject工厂方法-您可以在单元测试中传递模拟存储库,该存储库始终返回固定金额。


#2 楼



TaxCalculatorTaxCalculatorByDB包含相同的逻辑:仅用于测试。这是一种测试气味:生产中的测试逻辑。
我将使用模拟代替它。代码本身:

var gaRatio = _taxRepo.GetTaxRate() / (100 - _taxRepo.GetTaxRate());
return dAmount * gaRatio;


尝试解释为什么可行。为什么要返回25?否则只是噪音。

每个故事可以编写多个测试。例如,在无效输入上会发生什么或应该发生什么?
我认为TaxCalculator应该只包含一件事:获取捐赠金额并打印答案。故事1-4的要求应该结合起来。

我认为实现故事4意味着程序


应该询问事件类型,或者
为每种事件类型打印结果。


我找不到针对Story 3和Story 4的任何测试。
我现在无法进行测试(我没有使用C#编译器),但我认为故事4的值也应四舍五入。
GetObject(decimal taxRate)方法似乎不必要。故事2尚不清楚,但是由于没有关于管理员如何更改税率的任何细节,我想他们是用SQL命令(例如)而不是通过程序来实现的。


#3 楼

除了以前的出色文章,而且可能会挑剔,但为什么要添加大量评论?

////////////////////////////////////////////////////////////////////////////////


似乎不必要,如果我正在审查,那肯定会让我失望

注释中有错别字,同样,错别字也可能是挑剔的,但我肯定会认为“在编写代码时要特别注意”(我接受因为面试的情况不是正常的工作环境,所以可能有点苛刻!)。

我也建议不要使用两种方法来创建计算器。该示例似乎不需要工厂。

我想当您只有一个税率计算器要处理时,将其放进工厂可能会违反YAGNI原则。

编辑:

进一步挑剔!

您有一个块级变量'Amount'用大写A表示,这是我不希望的,这与其余变量不一致。

评论


\ $ \ begingroup \ $
+1在“在家做”测试中,没有任何理由可以格式化不一致或错别字。当他们给您时间时,将其擦亮。 :)
\ $ \ endgroup \ $
– David Harkness
2014-2-17在13:35

\ $ \ begingroup \ $
是的,在商业环境中,当人们将某些东西一推出功能就推出时,实际上这是相当普遍的,而不是花更多的时间重新阅读并确保将其清理干净。我个人发现您对代码的了解在功能正常运行之后已达到最大程度,这是重构和清理的最佳时间。
\ $ \ endgroup \ $
– Dougajmcdonald
17年1月14日在9:03