Помогите переделать Unit-тест. На форме AdForm имеется textbox, на который нужно написать два простых unit-теста. На проверку правильности ввода, и не правильности ввода пароля т.е. два отдельных unit-теста.
Код который хочу тестировать:
public void button5_Click(object sender, EventArgs e)
{
if (maskedTextBox4.Text == "qwerty") // вот это тестить хочу
{
AdForm adForm = new AdForm(this);
adForm.Show();
this.Hide();
}
}
Мой корявый наброски Unit-тестов:
[TestMethod()]
public void login()
{
AdForm n = new AdForm ();
string rez = n.insCl("qwerty");
string exp = "Успешно";
Assert.AreEqual(rez, exp);
}
[TestMethod]
public void login()
{
adForm n = new adForm ();
n.Text(true,"qwerty");
}
[TestMethod()]
public void login()
{
AdForm test1 = new AdForm ();
int a = test1.conv("qwerty");
Assert.AreEqual(a, 0);
}
P.S. Если кто поможет, буду благодарен. Мне бы один правильный вариант Unit-теста на проверку. Дальше сам. Не ругайтесь.
Код формы:
namespace roza
{
public partial class AuthForm : Form
{
public AuthForm()
{
InitializeComponent();
}
public void button5_Click(object sender, EventArgs e)
{
if (maskedTextBox4.Text == "qwerty") // вот это тестить хочу
{
AdForm adForm = new AdForm(this);
adForm.Show();
this.Hide();
}
}
}
}
}
Вот так должна выглядеть работа Unit-теста
Тест-->Выполнить-->Все тесты
Допустим, у вас есть сервис для проверки пароля
public class LoginService
{
public bool Login(string secret)
{
return secret == "qwerty";
}
}
И вы используете его на своей форме
public class LoginForm : Form
{
LoginService _loginService;
public LoginForm(LoginService loginService)
{
_loginService = loginService;
var passwordBox = new TextBox();
var loginButton = new Button() { Text = "Login", Top = 50 };
loginButton.Click += (sender, args) =>
{
var text = passwordBox.Text;
if (loginService.Login(text))
MessageBox.Show("Login sucessed");
else
MessageBox.Show("Login failed");
};
this.Controls.Add(passwordBox);
this.Controls.Add(loginButton);
}
}
Создание формы выглядит так:
var service = new LoginService();
var form = new LoginForm(service);
form.ShowDialog();
Результат выглядит так:
Тесты писать надо будет для сервиса, так как только он содержит логику, определяющую, правильный был передан пароль или нет. Пример 2 тестов - позитивный и негативный:
[TestMethod()]
public void login_failed()
{
var loginService = new LoginService();
var actual = loginService.Login("wrong password");
var expected = false;
Assert.AreEqual(actual, expected);
}
[TestMethod()]
public void login_sucessed()
{
var loginService = new LoginService();
var actual = loginService.Login("qwerty");
var expected = true;
Assert.AreEqual(actual, expected);
}
Вся проблема в том, что вы не отделили классы UI (ваши формочки) и бизнес-логику.
Это очень стандартная ошибка новичков: фигачить бизнес-логику прямо в buttonN_click.
Поэтому сначала вы должны научаться разделять логику предметной области от UI - и потом уже писать юнит-тесты на них.
А пока это у вас не будет юнит-тест, это будет что-то ближе к интеграционному тесты, либо юнит-тест, но хрупкий, который зависит и от UI и от фаз луны и от чего-нибудь ещё.
Посмотрите вот мои примеры юнит-тестов: у меня в проекте ни одной формы нет, а тесты есть.
Как вам нужно поступить в вашем случае. У вас есть некий класс формы, вам нужно объявить, что этот класс имеет зависимость от некоторого класса, реализующего интерфейс проверки пароля.
Было:
public partial class AuthForm : Form
{
public AuthForm()
{
InitializeComponent();
}
public void button5_Click(object sender, EventArgs e)
{
if (maskedTextBox4.Text == "qwerty") // вот это тестить хочу
{
AdForm adForm = new AdForm(this);
adForm.Show();
this.Hide();
}
}
}
Стало:
public partial class AuthForm : Form
{
public AuthForm(IPasswordCheckerService passwordCheckerService)
{
this.PasswordCheckerService = passwordCheckerService;
InitializeComponent();
}
private IPasswordCheckerService PasswordCheckerService { get; set; }
public void button5_Click(object sender, EventArgs e)
{
if (this.PasswordCheckerService.IsPasswordValid(maskedTextBox4.Text)) // вот это тестить хочу
{
AdForm adForm = new AdForm(this);
adForm.Show();
this.Hide();
}
}
}
public interface IPasswordCheckerService
{
bool IsPasswordValid(string password)
}
И вот с этим уже можно работать.
Вы можете создать кучу классов, которые реализуют данный интефейс - от простых, которые возвращают всегда true или которые проверяют что пароль равен какой-либо захардкоженной строке до очень сложных, которые лезут в реестр виндовс, базу данных, облако и т.п.
Вот простой пример класса, реализующего интерфейс:
public class SimplePasswordChecker : IPasswordCheckerService
{
public bool IsPasswordValid(string password)
{
return true;
}
}
А вот простой тест:
[Test]
public void IsPasswordValid_PasswordMatch_ReturnsTrue()
{
// Arrange
var checker = new SimplePasswordChecker();
// Act
var result = checker.IsPasswordValid("qwerty");
// Assert
Assert.IsTrue(result);
}
[Test]
public void IsPasswordValid_PasswordMismatch_ReturnsFalse()
{
// Arrange
var checker = new SimplePasswordChecker();
// Act
var result = checker.IsPasswordValid("asdf");
// Assert
Assert.IsFalse(result);
}
Разумеется, этот тест "не пройдёт". Как и полагается в TDD мы сначала написали красный тест, потом исправляем код класса SimplePasswordChecker на тот, который пройдёт тест.
Получившиеся классы никак не завязаны на то, какой у вас интерфейс - сегодня это winforms, завтра wpf, веб или мобильное приложение. А бизнес-логика остаётся отдельным проектом в решении, которое не имеет никаких зависимостей. Поэтому все эти классы бизнес-логики сразу отселяйте в отдельный проект и начинайте структурировать своё приложение - это и есть архитектура приложения, когда у вас слои разделяют обязанности, а не валят всё в одну кучу.
PS Как передавать зависимость на конструктор - оставляю вам на самостоятельную проработку. В идеале вообще такие вещи делаются при помощи DI.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
Необходимо преобразовать месяц даты в intВходная строка из потока выглядит следующим образом: "12
Подскажите как решить следующую проблемуЕсть TabControl с несколькими TabItem
Написал скрипт на шарпе, прикрепил его к обьекту игрока, по задумке изображение должно перемещаться по нажатию на стрелку вправо, но ничего...