|
Take Unit Testing to the Next LevelIcuTest ScenariosThere is a subtle problem with the introductory examples presented here. If a test fails, the code aborts and we may be left with a dangling window. To be safe (and pedantic) we need to insert a try/finally clause. [TestMethod]
public void TestMyWindow_safely() {
ICU.Invoke(() => {
MyWindow w = null; try {
w = new MyWindow(); w.Show(); w.DataContext = new MyViewModel(); ICU.CheckView(w, "MyWindowTest_with_ViewModel");
} finally {
w.Close(); } }); } This frequent pattern of invoke-try-new-show-finally-close is tedious and prone to cut-and-paste errors. To alleviate this, Scenarios were created. Scenarios capture frequently used patterns using a flexible Arrange, Act, Assert (or Given, When, Then) framework. Here is the above example using WindowScenario<T>. [TestMethod]
public void TestMyWindow_Using_Scenarios() {
var context = new WindowScenario<MyWindow>(); ICU.Given(context) // Arrange
.When(() => { // Act
context.Window.DataContext = new MyViewModel(); }) .Then(() => { // Assert
var w = context.Window;
ICU.CheckView(w, "MyWindowTest_with_ViewModel");
}) .Test(); } Note that there is no mention of invoke, try, new, show, finally or close; WindowScenario<T> handles everything. All you need to worry about is the actual test code. Optionally, you can add BDD (Behavior Driven Design) specifications to scenarios to help clarify the purpose of the test. [TestMethod]
public void TestMyWindow_Using_BDD() {
var context = new WindowScenario<MyWindow>(); ICU.Given(context) .AsA("Telephone Sanitizer")
.IWant("a list of dirty phone booths")
.SoThat("I can schedule which phones to clean")
.Then(() => {
var w = context.Window;
ICU.CheckView(w, "MyWindowTest");
w.DataContext = new MyViewModel(); ICU.CheckView(w, "MyWindowTest_with_ViewModel");
}) .Test(); } Scenarios can be subclassed or extended to produce incrementally more complex tests; tests that are sophisticated yet easy to use and understand. And There's More...IcuTest offers higher level tools specifically designed to help GUI testing. Here is an example that illustrates:
[TestMethod]
public void cannot_login_with_invalid_password() {
var context = new WindowScenario<ExampleLoginWindow>(); ICU.Given(context) // Optional BDD specs
.AsA("MyApp User")
.IWant("a login window")
.SoThat("I have secure access to MyApp data")
.When(() => {
// set wrong password using GUI automation
set_login(context.Window, "myname", "wrong password"); }) .Then(() => {
// window should display "invalid login" message
ICU.CheckView(context.Window, "login_with_invalid_pass");
}) .Test(); } void set_login(ExampleLoginWindow w, string user, string pass) {
var userBox = guiHelper.Find<TextBox>(w, "userBox"); var passBox = guiHelper.Find<PasswordBox>(w, "passwordBox"); var loginBtn = guiHelper.Find<Button>(w, "LoginButton"); userBox.Text = user; passBox.Password = pass; guiHelper.Click(loginBtn); }
|