我想制作一個rpn計算器并使用nunit為字典創建單元測驗來測驗操作,但我不知道如何制作。
static Stack<double> stack { get; set; } = new Stack<double>();
static Dictionary<string, Action> operators = new Dictionary<string, Action>
{
[" "] = () => { stack.Push(stack.Pop() stack.Pop()); },
["-"] = () => { var x = stack.Pop(); stack.Push(stack.Pop() - x); },
["*"] = () => { stack.Push(stack.Pop() * stack.Pop()); },
["/"] = () => { var x = stack.Pop(); if (x == 0) throw new DivideByZeroException(); stack.Push(stack.Pop() / x); },
["clr"] = () => { stack.Clear(); },
["!"] = () => { var x = stack.Pop(); stack.Push(x == 0 ? 1 : 0); },
["!="] = () => { stack.Push(stack.Pop() == stack.Pop() ? 0 : 1); },
["%"] = () => { var x = stack.Pop(); stack.Push(stack.Pop() % x); },
[" "] = () => { var x = stack.Pop(); x ; stack.Push(x); },
["--"] = () => { var x = stack.Pop(); x--; stack.Push(x); },
}
編輯:執行就像
while (true)
{
Display();
var readLine = Console.ReadLine();
var tokens = readLine.Split(" ").Where(t => t != string.Empty).ToArray();
foreach (var token in tokens)
{
try
{
operators[token].Invoke();
}
catch(KeyNotFoundException)
{
stack.Push(double.Parse(token));
}
}
}
uj5u.com熱心網友回復:
我認為您應該將stackandoperators作為private欄位放在一些class稱為 example的欄位中CalculatingService。之后,您應該創建public方法Calculate(...),它將return計算值:
public class CalculatingService : ICalculatingService
{
private readonly Stack<double> stack { get; set; }
private readonly Dictionary<string, Func<double>> operators;
public CalculatingService()
{
stack = new Stack<double>();
InitDictionary();
}
public double Calculate(string @operator) =>
operators[@operator].Invoke();
public void ClearData() => stack.Clear();
private void InitDictionary() => operators = new Dictionary<string, Func<double>>
{
[" "] = () => stack.Pop() stack.Pop(),
["-"] = () => { var x = stack.Pop(); return stack.Pop() - x; },
["*"] = () => stack.Pop() * stack.Pop(),
["/"] = () => { var x = stack.Pop(); if (x == 0) throw new DivideByZeroException(); return stack.Pop() / x; },
["!"] = () => { var x = stack.Pop(); return x == 0 ? 1 : 0; },
["!="] = () => stack.Pop() == stack.Pop() ? 0 : 1,
["%"] = () => { var x = stack.Pop(); return stack.Pop() % x; },
[" "] = () => { var x = stack.Pop(); x ; return x; },
["--"] = () => { var x = stack.Pop(); x--; return x; }
};
}
現在您可以為CalculatingService. 您可以Calculate(...)通過為 x 運算子撰寫 x 測驗方法來進行測驗。我不知道,你是如何管理stack的——你必須像我寫的那樣為管理撰寫額外public的方法。CalculatingServicestackClearData()
uj5u.com熱心網友回復:
我會先使它成為非靜態的。否則,除非您清除堆疊,否則每個測驗都會影響下一個測驗。如果您可以calculator = new Calculator()在每個測驗中進行,那就更容易了。
從外觀上看,操作作為字串發送到計算器。它沒有顯示,但我猜數字也是。這還不清楚。
為了確保您的計算器正常作業,您可能需要向其發送一些數字和運算,并確保在完成后計算器具有正確的結果。一種方法是使用引數化測驗。也就是說,您撰寫了一個測驗,但向它發送了多組輸入。
這是一個 NUnit 示例。請記住,我不知道您的計算器如何作業的確切細節,所以這更像是一個指標,而不是一個完美的例子。
首先,我必須創建一個基本Calculator類,因為使用靜態類撰寫單元測驗要困難得多。(但是等等,你的堆疊和字典不見了!更多關于那個。)
public class Calculator
{
public string DisplayedResult { get; }
public void SendInput(string input)
{
}
}
這個想法SendInput就像按下一個按鈕,當你按下一個按鈕時DisplayedResult會發生變化。因此,如果您按“2 2 2 =”,它將顯示“24”。如果按“5 / 0 =”,可能會顯示“錯誤”。如果有一個“清除”按鈕,那么“5 / 0 = C 2 2 =”可能會顯示“4”。(先有錯誤,然后清除,再進行操作。)
現在我們可以像這樣撰寫一個引數化的 NUnit 測驗:
[Test]
[TestCase("2 2 2 =","24")]
[TestCase("5 / 0 =", "error")]
[TestCase("5 / 0 = C 2 2 =", "4")]
public void Calculator_Displays_Expected_Results(string input, string expectedResult)
{
var inputsToSend = input.Split(' ');
var calculator = new Calculator();
foreach (var inputToSend in inputsToSend)
{
calculator.SendInput(inputToSend);
}
Assert.AreEqual(expectedResult, calculator.DisplayedResult);
}
每個測驗用例都有一個輸入——一系列由字串分隔的操作。這使得創建每個測驗用例變得容易。它也有預期的結果。我們期望計算器顯示什么?
測驗發送輸入并驗證您是否獲得了預期的結果。您可以將其分成多個測驗,或者您可以進行一個包含大量案例的大型測驗。您可以撰寫任意數量的測驗。您可以添加另一個引數來描述正在測驗的內容。
兩個重要細節:
設計必須考慮測驗。靜態類更難測驗。此外,如果該類公開了一個易于測驗的介面 - 輸入和輸出,則更容易測驗。如果某些東西難以測驗,則通常表示設計存在困難。所以我們會調整到更容易測驗的設計是很正常的。
字典和堆疊呢?如果這就是您想要實作計算器的方式,那很好 - 您可以添加它。也許該SendInput方法與它們互動并DisplayedResult根據需要更新。
重要的是測驗不會與實作細節相關聯。如果您改變主意,不使用堆疊和字典,并且撰寫完全不同的代碼來處理這些操作怎么辦?測驗仍將完全一樣有效。只要您的實作有效,無論它是什么,測驗都會通過。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/483071.html
上一篇:柴終誤傳
