有人可以帮助将遗留代码转换为TDD代码吗?

我试图用TDD重写一个方法。

这是没有数据库逻辑的原始方法,下面是我尝试重新编写它。 它不完整,因为我只是碰壁,不明白如何完成它。

我正在努力学习,无法解决,所以需要一些帮助。 谢谢阅读。

    //Original Method

    public class StringCalculator()
    {

    public List<ShipmentInformation> GetBoxRange(int BoxSize, int Quantity, ref string DVDType, ref string ErrorMessage)
    {

        //Get Connection String


        //Do Database Queries and return shipmentInfo variable as List<ShipmentInformation>

        var DVDTotals = shipmentInfo.GroupBy(x => x.DVDType).Select(x => new { DVDType = x.Key, Total = x.Sum(y => (y.DVDEndID - y.DVDStartID) + 1) });

        if (DVDTotals.Count() == 0 || DVDTotals.All(x => x.Total < Quantity))
        {
            ErrorMessage = "There is not enough data to create a shipment based on the quantity";
            return new List<ShipmentInformation>();
        }


        //Select the one with the largest amount of stock
        var LargestDVDType = DVDTotals.Aggregate((l, r) => l.Total > r.Total ? l : r).DVDType;

        var LargestDVDTypeSelection = shipmentInfo.Where(x => x.DVDType == LargestDVDType);

        long previousDVDStartID = 0;

        //Make sure ranges are sequential
        List<ShipmentInformation> SequentialBoxResults = new List<ShipmentInformation>();
        foreach (var item in LargestDVDTypeSelection)
        {
            if (item.DVDStartID - previousDVDStartID == BoxSize || previousDVDStartID == 0) 
            {
                SequentialBoxResults.Add(item);
            }
            else
            {
                SequentialBoxResults.Clear();
                SequentialBoxResults.Add(item);
            }

            previousDVDStartID = item.DVDStartID;

            if (BoxSize * SequentialBoxResults.Count == Quantity)
            {
                break;
            }
        }

        if (SequentialBoxResults.Count == 0 || BoxSize * SequentialBoxResults.Count != Quantity)
        {
            ErrorMessage = "There are no available ranges to create a shipment based on the quantity";
            return new List<ShipmentInformation>(); ;
        }

        List<ShipmentInformation> Results = new List<ShipmentInformation>();
        var Genres = SequentialBoxResults.GroupBy(x => x.Genre);
        foreach (var Genre in Genres)
        {
            var orderedGenres = Genre.OrderBy(x => x.DVDStartID);

            ShipmentInformation shipment = new ShipmentInformation();
            shipment.Genre = Genre.Key;
            shipment.DVDStartID = orderedGenres.First().DVDStartID;
            var lastItem = orderedGenres.Last();
            shipment.DVDEndID = lastItem.DVDEndID;
            shipment.DVDType = lastItem.DVDType;

            Results.Add(shipment);
        }

        //We have our shipment recordsnow split them up if any are over 75000

        for (int i = 0; i < Results.Count; i++)
        {
            long rangeSize = Results[i].DVDEndID - Results[i].DVDStartID + 1;

            double noOfLoops = Math.Ceiling(rangeSize / 75000D);
            long remainder = rangeSize % 75000;

            if (noOfLoops > 1)
            {
                bool AddedRecord = false;
                for (int j = 0; j < noOfLoops; j++)
                {
                    long shipmentSize = 0;

                    if (j == (noOfLoops - 1))
                    {
                        shipmentSize = remainder;
                        if (AddedRecord)
                            Results.Add(new ShipmentInformation() { DVDStartID = Results.Last().DVDEndID + 1, DVDEndID = Results.Last().DVDEndID + 1 + (shipmentSize - 1), Genre = Results.Last().Genre });
                        else
                            Results.Add(new ShipmentInformation() { DVDStartID = Results[i].DVDEndID + 1, DVDEndID = Results[i].DVDEndID + 1 + (shipmentSize - 1), Genre = Results[i].Genre });
                    }
                    else
                    {
                        shipmentSize = 75000;
                        if (j == 0)
                        {
                            Results[i].DVDEndID = Results[i].DVDStartID + (shipmentSize - 1);
                        }
                        else if (j == 1)
                        {
                            Results.Add(new ShipmentInformation() { DVDStartID = Results[i].DVDEndID + 1, DVDEndID = Results[i].DVDEndID + 1 + (shipmentSize - 1), Genre = Results[i].Genre });
                            AddedRecord = true;
                        }
                        else
                        {
                            Results.Add(new ShipmentInformation() { DVDStartID = Results.Last().DVDEndID + 1, DVDEndID = Results.Last().DVDEndID + 1 + (shipmentSize - 1), Genre = Results.Last().Genre });
                            AddedRecord = true;
                        }
                    }
                }
            }
        }

        return Results;

    }
  }

   //New Method with Tests

  public List<ShipmentInformation> GetBoxRange(int BoxSize, int Quantity, DateTime CutOffDate, IDataProvider Provider, ref string DVDType, ref string ErrorMessage)
    {
        if (BoxSize == 0)
        {
            ErrorMessage = "Please enter a BoxSize";
        }

        if (Quantity == 0)
        {
            ErrorMessage = "Please enter a Quantity";
        }


        if (!String.IsNullOrWhiteSpace(ErrorMessage))
        {
            return new List<ShipmentInformation>();
        }

        List<ShipmentInformation> Data = Provider.GetData();

        if (Data.Count == 0)
        {
            ErrorMessage = "Database failed to return data";
            return new List<ShipmentInformation>();
        }

        List<ShipmentInformation> OrderedData = GetSequentialBoxes(Data, BoxSize, Quantity);

        if (OrderedData.Count == 0)
        {
            ErrorMessage = "No sequential data found";
            return new List<ShipmentInformation>();
        }

        //I'm not sure how to continue from here - I started writing GetRecordsPerGenre but got lost in what I'm trying to do. I still need to check if size is over 75000

        return OrderedData;
    }

    public virtual List<ShipmentInformation> GetSequentialBoxes(List<ShipmentInformation> Data, int BoxSize, int Quantity)
    {
        if (Data.Count == 0)
            return new List<ShipmentInformation>();

        var orderedData = Data.OrderBy(x => x.DVDStartID);
        if (!orderedData.SequenceEqual(Data))
            return new List<ShipmentInformation>();

        var DVDTotals = Data.GroupBy(x => x.DVDType).Select(x => new { DVDType = x.Key, Total = x.Sum(y => (y.DVDEndID - y.DVDStartID) + 1) });

        if (DVDTotals.Count() == 0 || DVDTotals.All(x => x.Total < Quantity))
        {
            return new List<ShipmentInformation>();
        }

        var LargestDVDType = DVDTotals.Aggregate((l, r) => l.Total > r.Total ? l : r).DVDType;

        Data = Data.Where(x => x.DVDType == LargestDVDType).ToList();

        List<ShipmentInformation> returnData = new List<ShipmentInformation>();
        long previousDVDStartID = 0;
        foreach (var item in Data)
        {
            if (previousDVDStartID == 0 || item.DVDStartID - previousDVDStartID == BoxSize)
            {
                returnData.Add(item);
            }
            else
            {
                returnData.Clear();
                returnData.Add(item);
            }

            previousDVDStartID = item.DVDStartID;

            if (returnData.Count * BoxSize == Quantity)
                break;
        }

        return returnData.OrderBy(x => x.DVDStartID).ToList();
    }

    public List<ShipmentInformation> GetRecordsPerGenre(List<ShipmentInformation> Data)
    {
        List<ShipmentInformation> Results = new List<ShipmentInformation>();
        var Genres = Data.GroupBy(x => x.Genre);
        foreach (var Genre in Genres)
        {
            var orderedGenres = Genre.OrderBy(x => x.DVDStartID);

            ShipmentInformation shipment = new ShipmentInformation();
            shipment.Genre = Genre.Key;
            shipment.DVDStartID = orderedGenres.First().DVDStartID;
            var lastItem = orderedGenres.Last();
            shipment.DVDEndID = lastItem.DVDEndID;
            shipment.DVDType = lastItem.DVDType;

            Results.Add(shipment);
        }

        return Results;
    }




   //Tests

   [TestFixture]
    public class GetBoxRangeMethod
    {
        private StringCalculator CreateNewCalculator()
        {
            return new StringCalculator();
        }

        [TestCase(0, 1)]
        [TestCase(1, 0)]
        public void ZeroValuesForBoxSizeOrQuantity_ReturnsErrorAndEmptyList(int BoxSize, int Quantity)
        {
            StringCalculator sc = CreateNewCalculator();

            string ErrorMessage = "";
            string ChipType = "";
            FakeDataProvier provider = new FakeDataProvier(new List<ShipmentInformation>());
            List<ShipmentInformation> result = sc.GetBoxRange(BoxSize, Quantity, new DateTime(2012, 01, 01), "A", provider, ref ChipType, ref ErrorMessage);

            Assert.AreNotEqual("", ErrorMessage);
            Assert.AreEqual(0, result.Count);
        }

        [Test]
        public void EmptyBookTypeString_ReturnsErrorAndEmptyList()
        {
            StringCalculator sc = CreateNewCalculator();

            string ErrorMessage = "";
            string ChipType = "";

            FakeDataProvier provider = new FakeDataProvier(new List<ShipmentInformation>());

            List<ShipmentInformation> result = sc.GetBoxRange(1, 1, new DateTime(2012, 01, 01), "", provider, ref ChipType, ref ErrorMessage);

            Assert.AreNotEqual("", ErrorMessage);
            Assert.AreEqual(0, result.Count);
        }

        [Test]
        public void EmptyDBData_ReturnsErrorAndEmptyList()
        {
            StringCalculator sc = CreateNewCalculator();

            string ErrorMessage = "";
            string ChipType = "";
            FakeDataProvier provider = new FakeDataProvier(new List<ShipmentInformation>());

            List<ShipmentInformation> result = sc.GetBoxRange(1, 1, new DateTime(2012, 01, 01), "A", provider, ref ChipType, ref ErrorMessage);

            Assert.AreNotEqual("", ErrorMessage);
            Assert.AreEqual(0, result.Count);
        }

        [Test]
        public void EmptyOrderedData_ReturnsErrorAndEmptyList()
        {
            FakeShipmentCalculator sc = new FakeShipmentCalculator();

            string ErrorMessage = "";
            string ChipType = "";
            FakeDataProvier provider = new FakeDataProvier(new List<ShipmentInformation>() { new ShipmentInformation() { ChipType = "A", StartPP = 1, EndPP = 2, JacketNo = "A", ReqNo = "B" } });

            List<ShipmentInformation> result = sc.GetBoxRange(1, 1, new DateTime(2012, 01, 01), "A", provider, ref ChipType, ref ErrorMessage);

            Assert.AreNotEqual("", ErrorMessage);
            Assert.AreEqual(0, result.Count);
        }

    }

    //Integration test
    [TestFixture]
    public class GetDataMethod
    {

    }

    [TestFixture]
    public class GetSequentialBoxes
    {
        private StringCalculator CreateNewCalculator()
        {
            return new StringCalculator();
        }

        [Test]
        public void MethodCalled_DoesntReturnNull()
        {
            StringCalculator sc = CreateNewCalculator();

            List<ShipmentInformation> result = sc.GetSequentialBoxes(new List<ShipmentInformation>(), 100, 1);

            Assert.IsNotNull(result);
        }

        [Test]
        public void EmptyDataPassedIn_ReturnsEmptyData()
        {
            StringCalculator sc = CreateNewCalculator();

            List<ShipmentInformation> result = sc.GetSequentialBoxes(new List<ShipmentInformation>(), 100, 1);

            Assert.AreEqual(0, result.Count);
        }

        [Test]
        public void OrderedData_ReturnsOrderedData()
        {
            StringCalculator sc = CreateNewCalculator();

            List<ShipmentInformation> inputData = new List<ShipmentInformation>();

            ShipmentInformation data = new ShipmentInformation() { ChipType = "A", StartPP = 1, EndPP = 2, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            data = new ShipmentInformation() { ChipType = "A", StartPP = 3, EndPP = 4, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            List<ShipmentInformation> result = sc.GetSequentialBoxes(inputData, 2, 1);

            ShipmentInformation firstItem = result.FirstOrDefault();
            ShipmentInformation secondItem = result.LastOrDefault();

            Assert.IsTrue(firstItem.StartPP == 1 && secondItem.StartPP == 3);
        }

        [Test]
        public void UnOrderedData_ReturnsEmptyData()
        {
            StringCalculator sc = CreateNewCalculator();

            List<ShipmentInformation> inputData = new List<ShipmentInformation>();

            ShipmentInformation data = new ShipmentInformation() { ChipType = "A", StartPP = 3, EndPP = 4, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            data = new ShipmentInformation() { ChipType = "A", StartPP = 1, EndPP = 2, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            int NUMBER_GREATER_THAN_ONE = 2;
            List<ShipmentInformation> result = sc.GetSequentialBoxes(inputData, NUMBER_GREATER_THAN_ONE, 1);

            Assert.AreEqual(0, result.Count);
        }

        [Test]
        public void SequenceJumps_ClearsListAndStartsAgain()
        {
            StringCalculator sc = CreateNewCalculator();

            List<ShipmentInformation> inputData = new List<ShipmentInformation>();

            ShipmentInformation data = new ShipmentInformation() { ChipType = "A", StartPP = 1, EndPP = 2, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            data = new ShipmentInformation() { ChipType = "A", StartPP = 5, EndPP = 6, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            List<ShipmentInformation> result = sc.GetSequentialBoxes(inputData, 2, 1);

            Assert.IsTrue(result.First().StartPP == 5);
        }

        [Test]
        public void LargestNumberOfItemsWithSameChipType_ReturnsDataWithOnlyThatChipType()
        {
            StringCalculator sc = CreateNewCalculator();

            List<ShipmentInformation> inputData = new List<ShipmentInformation>();

            ShipmentInformation data = new ShipmentInformation() { ChipType = "A", StartPP = 1, EndPP = 2, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            data = new ShipmentInformation() { ChipType = "A", StartPP = 3, EndPP = 4, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            data = new ShipmentInformation() { ChipType = "B", StartPP = 5, EndPP = 6, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            int BoxSizeSlashSequenceJumpAllowed = 2;

            List<ShipmentInformation> result = sc.GetSequentialBoxes(inputData, BoxSizeSlashSequenceJumpAllowed, 1);

            Assert.IsTrue(result.All(x => x.ChipType == "A"));
        }

        [Test]
        public void TotalNumberOfRecordsPerChipTypeLessThanQuantity_ReturnsEmptyData()
        {
            StringCalculator sc = CreateNewCalculator();

            List<ShipmentInformation> inputData = new List<ShipmentInformation>();

            ShipmentInformation data = new ShipmentInformation() { ChipType = "A", StartPP = 1, EndPP = 2, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            data = new ShipmentInformation() { ChipType = "A", StartPP = 3, EndPP = 4, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            data = new ShipmentInformation() { ChipType = "B", StartPP = 5, EndPP = 6, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            int BoxSizeSlashSequenceJumpAllowed = 2;
            int Quantity = 5;

            List<ShipmentInformation> result = sc.GetSequentialBoxes(inputData, BoxSizeSlashSequenceJumpAllowed, Quantity);

            Assert.AreEqual(0, result.Count);
        }

        [Test]
        public void DataReturned_WhenQuantityReached()
        {
            StringCalculator sc = CreateNewCalculator();

            List<ShipmentInformation> inputData = new List<ShipmentInformation>();

            ShipmentInformation data = new ShipmentInformation() { ChipType = "A", StartPP = 1, EndPP = 2, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            data = new ShipmentInformation() { ChipType = "A", StartPP = 3, EndPP = 4, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            data = new ShipmentInformation() { ChipType = "A", StartPP = 5, EndPP = 6, JacketNo = "A", ReqNo = "B" };
            inputData.Add(data);

            int BoxSizeSlashSequenceJumpAllowed = 2;
            int Quantity = 4;

            List<ShipmentInformation> result = sc.GetSequentialBoxes(inputData, BoxSizeSlashSequenceJumpAllowed, Quantity);

            Assert.AreEqual(2, result.Count);
        }
    }

    [TestFixture]
    public class GetRecordsPerGenre
    {
        private StringCalculator CreateNewCalculator()
        {
            return new StringCalculator();
        }

        [Test]
        public void MethodCalled_DoesntReturnNull()
        {
            StringCalculator sc = CreateNewCalculator();

            List<ShipmentInformation> result = sc.GetRecordsPerSerialRange(new List<ShipmentInformation>());

            Assert.IsNotNull(result);
        }

        [Test]
        public void EmptyDataPassedIn_ReturnsEmptyData()
        {
            StringCalculator sc = CreateNewCalculator();

            List<ShipmentInformation> result = sc.GetRecordsPerSerialRange(new List<ShipmentInformation>());

            Assert.AreEqual(0, result.Count);
        }

        [Test]
        public void Data_ReturnsGroupedByData()
        {
            StringCalculator sc = CreateNewCalculator();

            List<ShipmentInformation> inputData = new List<ShipmentInformation>();

            ShipmentInformation data = new ShipmentInformation();
            data.ChipType = "A";
            data.ReqNo = "B";
            data.JacketNo="C";
            data.StartPP = 1;
            data.EndPP = 2;

            inputData.Add(data);

            data = new ShipmentInformation();

            data.ChipType = "A";
            data.ReqNo = "B";
            data.JacketNo = "C";
            data.StartPP = 1;
            data.EndPP = 2;

            inputData.Add(data);

            List<ShipmentInformation> result = sc.GetRecordsPerSerialRange(inputData);

            Assert.AreEqual(1, result.Count);
        }
    }
采纳答案:

在乔恩,你可能会因为一个菜鸟而咬得太厉害。 使用新功能实现TDD,而不是现有功能。 在这种情况下,您不仅要引入测试,TDD,模拟。 但现在你也引入了重构(又一个新概念)。

一旦你掌握了绿地代码上TDD的基础知识,你就可以将它应用于棕地代码和重构。

最后一点:TDD不需要嘲笑,嘲讽是一个与TDD兼容的独立概念,但并不是必需的。 TDD,简单地说:通过测试推动设计。

author: jason-meckley

参考更多解答: Can someone help convert legacy code into TDD code? Beginner pulling his hair out ,转载请保留出处有人可以帮助将遗留代码转换为TDD代码吗?及作者信息

Statement: We respect knowledge and authors. Since the content comes from the Internet and is intended for scientific research, any reprinters should retain the author's signature and origin. If you are the author of the content and feel in dispute, please contact email: 1076545519@qq.com. We will find out the situation and deal with it in time. We sincerely thank the author for his hard work.


更多:c#