私は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);
}
}
"何をするのが最善で、私は物事を模倣する必要がありますか?"これは何を意味するのでしょうか?あなたにはテストがあります。彼らは失敗するのだろうか?あなたはコードを書く必要があります。彼らはパスしますか?あなたはコードを書いています。あなたはどこにいるのですか?また、コードサンプルを、問題を示す**最小の**コードサンプルに減らしてください。 **特に**あなたの問題は何ですか? –
は、多くのコードを分割して征服しています。クラスを1つずつ再構築し、メソッドをスタブしたり、途中でテストしたり、ビルド時にテストクラスやメソッドを構築したりしてください。あなたがこれをリファクタリングするのに気をつけているなら、テストクラスとメソッドを構築する時間を正当化することが重要です。 – jamesTheProgrammer
あなたのメソッドは、新しいものであっても、あまりにも多くのことをしようとしています。メソッド名が示すように、目的はボックス範囲を取得することです。ただし、エラーメッセージの処理も行います。これが唯一のことではありません。これにより、テストするのがずっと難しくなります。 – Holystream