#c# #unit-testing #testing #uwp
#c# #модульное тестирование #тестирование #uwp
Вопрос:
У меня есть этот калькулятор, который я сделал в UWP. Он может складывать, умножать, вычитать, делать деления, преобразовывать градусы Цельсия в градусы Фаренгейта и наоборот.
Моя проблема в том, что мне нужен способ его тестирования, чтобы я мог добавлять, вычитать, делить, умножать в одном методе тестирования. А также протестируйте, чтобы я мог взять значение Цельсия и преобразовать его в градусы Фаренгейта, и все это в тестовом методе.
Я могу изменить его так, чтобы некоторые из моих методов стали общедоступными, а не частными, но я не знаю, как мне следует протестировать некоторые из них?
Мои методы тестирования находятся в верхней части кода.
using NUnit.Framework;
using System;
using System.Data;
using System.Reflection;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352amp;clcid=0x409
namespace Calc
{
/// <summary>
/// A calculator, namespace start.
/// </summary>
///
/// Public start, mainpage.
public sealed partial class MainPage : Page
{
/// Input for Celcius/Farh.
string input;
/// <summary>
/// Testing celcius / F.
/// </summary>
[TestMethod]
private void TestDifferentScales()
{
}
/// <summary>
/// Test method - testing all functions regarding mathematical equations!
/// </summary>
[TestMethod()]
public void AdditionTest()
{
}
/// <summary>
/// Start main program!
/// </summary>
public MainPage()
{
//Startar allt.
this.InitializeComponent();
}
/// <summary>
/// Button for number 1.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click(object sender, RoutedEventArgs e)
{
textBox.Text = '1';
input = "1";
}
/// <summary>
/// Button for number 2.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_1(object sender, RoutedEventArgs e)
{
textBox.Text = '2';
input = "2";
}
/// <summary>
/// Button for number 3.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_2(object sender, RoutedEventArgs e)
{
textBox.Text = '3';
input = "3";
}
/// <summary>
/// Button for number 4.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_3(object sender, RoutedEventArgs e)
{
textBox.Text = '4';
input = "4";
}
/// <summary>
/// Button for number 5.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_4(object sender, RoutedEventArgs e)
{
textBox.Text = '5';
input = "5";
}
/// <summary>
/// Button for number 6.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_5(object sender, RoutedEventArgs e)
{
textBox.Text = '6';
input = "6";
}
/// <summary>
/// Button for number 7.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_6(object sender, RoutedEventArgs e)
{
textBox.Text = '7';
input = "7";
}
/// <summary>
/// Button for number 8.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_7(object sender, RoutedEventArgs e)
{
textBox.Text = '8';
input = "8";
}
/// <summary>
/// Button for number 9.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_8(object sender, RoutedEventArgs e)
{
textBox.Text = '9';
input = "9";
}
/// <summary>
/// Button for numbers 42 "Marcus".
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_9(object sender, RoutedEventArgs e)
{
textBox.Text = "42";
input = "42";
}
/// <summary>
/// Button for number 0.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_10(object sender, RoutedEventArgs e)
{
textBox.Text = '0';
input = "0";
}
/// <summary>
/// Button for multiplication of equation "F = M*A".
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_11(object sender, RoutedEventArgs e)
{
/* F = M * A
* Denna ekvation är simpel och man lär sig den redan i början utav Fysik 1.
* Ekvationen är inte specifik, så som tex "F = M * G" då gravitationen kan bli ett "fixed" värde som
* går mellan 9,802 och 9,820.
* Anledningen till varför denna är så simpel är för att jag ville bevisa att det gick att ha många komplikaitoner
* i ett knapp tryck. Så denna skulle lika gärna kunnat vara knappen för multiplikation.
*/
textBox.Text = '*';
}
/// <summary>
/// Button for addition.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_ClickPlus(object sender, RoutedEventArgs e)
{
/* "Exceptions without Execeptions"
* Här försökte jag att gå runt utan att behöva använda en
* try/catch eller Exception inför min "data table" på min "=" knapp.
* Men, som sagt, det är ingen skillnad här och på min knapp för "F = M * A".
* Det finns ju klara skillander, jag har försökt att se till så att jag går tillbaka ett
* steg ifall det finns flera matematiska karaktärer.
*
* MEN: Det skapar problem då jag fortfarande ville kunna köra "6--1 = 7" utan att krasha allt.
*
*/
var last = textBox.Text;
if (last[last.Length - 1] != ' ' || last[last.Length - 1] != '-' || last[last.Length - 1] != '*' || last[last.Length - 1] != '/')
{
textBox.Text = ' ';
}
else
{
textBox.Text = last.Remove(last.Length - 1, 1);
textBox.Text = ' ';
}
}
/// <summary>
/// Button for subtraction.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_ClickMinus(object sender, RoutedEventArgs e)
{
var last = textBox.Text;
if (last[last.Length - 1] != ' ' || last[last.Length - 1] != '-' || last[last.Length - 1] != '*' || last[last.Length - 1] != '/')
{
textBox.Text = '-';
}
else
{
textBox.Text = last.Remove(last.Length - 1, 1);
textBox.Text = '-';
}
}
/// <summary>
/// Button for multiplication.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_ClickTimes(object sender, RoutedEventArgs e)
{
var last = textBox.Text;
if (last[last.Length - 1] != ' ' || last[last.Length - 1] != '-' || last[last.Length - 1] != '*' || last[last.Length - 1] != '/')
{
textBox.Text = '*';
}
else
{
textBox.Text = last.Remove(last.Length - 1, 1);
textBox.Text = '*';
}
}
/// <summary>
/// Button for division.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_ClickDEv(object sender, RoutedEventArgs e)
{
var last = textBox.Text;
if (last[last.Length - 1] != ' ' || last[last.Length - 1] != '-' || last[last.Length - 1] != '*' || last[last.Length - 1] != '/')
{
textBox.Text = '/';
}
else
{
textBox.Text = last.Remove(last.Length - 1, 1);
textBox.Text = '/';
}
}
/// <summary>
/// Button for "Equal", the equal button.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_ClickEqual(object sender, RoutedEventArgs e)
{
/* Exception.
* Jag prövade att unit testa här med en thread timer för att kunna
* skriva ett meddelande i boxen typ "Error: Please try again"
* och sen rensa allt, men det gav error, det funkade men jag ville
* inte ha något error med så jag tog bort den från min "catch".
*
*/
try
{
object q = new DataTable().Compute(textBox.Text, null);
textBox.Text = q.ToString();
}
catch
{
/*
* Här återställer jag bara allt.
*/
textBox.Text = string.Empty;
input = string.Empty;
}
}
/// <summary>
/// Button for reset of calcuator.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_ClickReset(object sender, RoutedEventArgs e)
{
/*
* Åter ställer här på "ClickReset" också.
*/
textBox.Text = string.Empty;
input = string.Empty;
}
/// <summary>
/// Button from F to C.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_fc_(object sender, RoutedEventArgs e)
{
/*
* Här så var jag tvungen att gå fram och tillbaka med att
* konvertera saker från och till int och string.
* Multiplicerade och addade 32 eller tog bort 32 för att
* få rätt värden i slutet.
*/
int value = int.Parse(input);
int after = value - 32;
int a = (int)(decimal.Divide(after, (decimal)1.8));
string answer = a.ToString();
textBox.Text = string.Empty;
textBox.Text = answer;
}
/// <summary>
/// Button from C to F.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void Button_Click_cf_(object sender, RoutedEventArgs e)
{
int value = int.Parse(input);
int a = (int)(decimal.Multiply(value, (decimal)1.8) 32);
string answer = a.ToString();
textBox.Text = string.Empty;
textBox.Text = answer;
}
}
}
Комментарии:
1. В общем, ваши тесты должны быть в другом проекте модульного тестирования. Для лучшей тестируемости вы хотите абстрагировать всю логику калькулятора в другой класс, где основная функциональность будет представлена в виде общедоступных методов, которые вы можете тестировать независимо от пользовательского интерфейса.
2. Проверьте шаблон MVVM, тогда тестирование должно быть простым 🙂
3.См. Калькулятор с WPF (обзор кода).
4. Я могу дать вам исчерпывающий метод, с помощью которого вы комбинируете умножение, деление, сложение, вычитание и скобки, но вам нужно кое-что знать о преобразовании инфиксных выражений в постфиксные. Конечно, это очень просто
5. @meysamasadi Это было бы неплохо!
Ответ №1:
Позвольте мне привести вам пример, который избавит вас от пользовательского ввода. Вам нужно разрешить только определенные символы на входе. Если вы знаете о преобразовании инфиксных выражений в постфиксные, понимание примера будет отличным.
И вы создаете самый продвинутый калькулятор с наименьшим количеством кода.
Входные фразы не должны содержать пробела, в этом случае удалите пробелы.
Шаг 1. В следующих строках показано, как использовать
//real example in world
string infix = "(((13 26)*12)-15 15*(20/6))";
List<string> arrayPostfix;
if (ValidBraces(infix))
{
convertToPostfixArray(ref infix, out arrayPostfix);
double result = calculate(arrayPostfix);
Console.WriteLine(result);
}
else
Console.WriteLine("invalid experssion***********************");
Шаг 2. Метод проверки правильности фигурных скобок
static bool ValidBraces(string infix)
{
bool valid = true;
int i = 0;
Stack<char> symbls = new Stack<char>();
while (i < infix.Length)
{
if (infix[i] == '(')
symbls.Push(infix[i]);
if (infix[i] == ')')
if (symbls.Count == 0)
{
valid = false;
break;
}
else
{
char ch = symbls.Pop();
if (ch != '(')
{
valid = false;
break;
}
}
i ;
}
if (symbls.Count > 0)
valid = false;
return valid;
}
Шаг 3. Способ преобразования инфиксных выражений в постфиксные
static bool convertToPostfixArray(ref string infix, out List<string> postfix)
{
int prio = 0;
postfix = new List<string>();
Stack<Char> s1 = new Stack<char>();
string value = "";
for (int i = 0; i < infix.Length; i )
{
char ch = infix[i];
if (ch == '(')
{
s1.Push(ch);
}
else if (ch == ')')
{
if (!string.IsNullOrEmpty(value))
{
postfix.Add(value);
value = string.Empty;
}
while (s1.Peek() != '(')
{
postfix.Add(s1.Pop().ToString());
}
s1.Pop();
}
else if (ch == ' ' || ch == '-' || ch == '*' || ch == '/')
{
if (!string.IsNullOrEmpty(value))
{
postfix.Add(value);
value = string.Empty;
}
if (s1.Count <= 0)
{
s1.Push(ch);
}
else
{
if (s1.Peek() == '*' || s1.Peek() == '/')
prio = 1;
else
prio = 0;
if (prio == 1)
{
char c = s1.Peek();
if (c != '(')
postfix.Add(s1.Pop().ToString());
i--;
}
else
{
if (ch == ' ' || ch == '-')
{
char c = s1.Peek();
if (c != '(')
postfix.Add(s1.Pop().ToString());
s1.Push(ch);
}
else
s1.Push(ch);
}
}
}
else
{
value = ch.ToString();
}
}
if (!string.IsNullOrEmpty(value))
{
postfix.Add(value);
value = string.Empty;
}
int len = s1.Count;
for (int j = 0; j < len; j )
{
char c = s1.Pop();
if (c != '(')
postfix.Add(c.ToString());
}
return true;
}
Шаг 4. Метод вычисления Postfix
static double calculate(List<string> postfix)
{
Stack<double> stack = new Stack<double>();
foreach (string item in postfix)
{
double answer = 0;
if (item == " " || item == "-" || item == "*" || item == "/")
{
char charVal = System.Convert.ToChar(item);
double operand1 = ((Double)stack.Pop());
double operand2 = ((Double)stack.Pop());
answer = Solve(charVal, operand1, operand2);
stack.Push((answer));
}
else
{
stack.Push(Convert.ToDouble(item));
}
}
return stack.Pop();
}
public static double Solve(char operation, double operand1, double operand2)
{
double answer = 0;
switch (operation)
{
case ' ':
answer = operand1 operand2;
break;
case '-':
answer = operand2 - operand1;
break;
case '*':
answer = operand1 * operand2;
break;
case '/':
answer = operand2 / operand1;
break;
}
return answer;
}