Quantcast
Channel: XAF Team Blog
Viewing all articles
Browse latest Browse all 148

XAF - Unit and Functional Testing with Blazor UI

$
0
0
I want to share our vision on unit/functional testing as early as possible, because it is important to XAF's target audience - development teams creating complex enterprise apps. Increased support traffic regarding this topic and our recent roadmap surveys underscore the importance of this subject. Everything I will describe below is already battle-tested by our team internally.

Functional Tests

We continue to use our cross-platform EasyTest engine for functional testing. Chrome or FireFox web browser interaction is powered by Selenium.

If you have Google Chrome installed on your desktop, you can run automatic tests for our online Blazor demo with Visual Studio or the command prompt - no special configuration is required. For more information, refer to the following KB article: How to use EasyTest and Selenium WebDriver to create functional tests for XAF's Blazor UI with C#, VB.NET or a human-readable scripting language.

The following are supported:

1. Functional tests with C# or VB.NET (for developers).

using DevExpress.ExpressApp.EasyTest.BlazorAdapter;
using DevExpress.ExpressApp.EasyTest.BlazorAdapter.TestControls;
using DevExpress.ExpressApp.EasyTest.BlazorAdapter.Utils;
using NUnit.Framework;

namespace MainDemo.Blazor.FunctionalTest {
    public class TakeScreenshortTests : FunctionalTestBase {
        public TakeScreenshortTests() {
            TestSettings.DefaultApplicationUrl = "https://demos.devexpress.com/XAF/BlazorDemo/";
        }
        [Test]
        public void StartPageScreenshot() {
            CompareScreenshot.Exec(TestSettings.CombineWithCWD(@"..\..\Images\MainDemo.png"), Browser.GetImage());
        }
        [Test]
        public void DeatailViewScreenshot() {
            var mainListView = new MainListView(Driver);
            mainListView.Grid.RowClick("Hewitt Aiello");
            CompareScreenshot.Exec(TestSettings.CombineWithCWD(@"..\..\Images\ContactMainDemo.png"), Browser.GetImage());
        }
        [Test]
        public void CRUD() {
            var contactsListView = new MainListView(Driver);
            contactsListView.Toolbar.FindControl("New").Act(null);
            var contactDetailView = new MainDetailView(Driver);
            ((IControlText)contactDetailView.Form.FindControl(TestControlType.Field, "First Name")).Text = "TestName";
            contactDetailView.Toolbar.FindControl("Save and Close").Act();
            contactsListView = new MainListView(Driver);
            contactsListView.Grid.RowClick("TestName");
            contactDetailView = new MainDetailView(Driver);
            contactDetailView.Toolbar.FindControl("Delete").Act();
            wait.Until(BlazorAppResponseAwaiter.IsAlertPresent);
            var dialog = new DialogTestControl(Driver);
            Assert.AreEqual("You are about to delete the selected record(s). Do you want to proceed?", dialog.Text);
            dialog.Act("Yes");
            wait.Until(SeleniumUtils.ElementExists(GridTestControl.ByGrid));
            contactsListView = new MainListView(Driver);
            Assert.AreEqual(0, contactsListView.Grid.WebElement.FindElements(GridTestControl.ByRowByValue("TestName")).Count);
        }
    }
}

2. Functional tests with human-readable scripts (for non-developers).

#Application MainDemoBlazor_Chrome

*Action New
*FillForm
 First Name = TestContact
*Action Save and Close

*ProcessRecord 
 Full Name = TestContact

*Action Delete

*HandleDialog
 Respond = Yes
 Message = You are about to delete the selected record(s). Do you want to proceed?

!ProcessRecord 
 Full Name = TestContact

Unit Tests

Thanks to XAF's modular architecture and mocks, we can keep our unit tests as lightweight as possible. Unit tests for Blazor UI are no different than XAF tests for WinForms or WebForms. Consider the following test cases: 

1. Test whether a Controller's Action is active in DetailView and ListView.

#if DebugTest
using DevExpress.ExpressApp.Base.Tests;
using DevExpress.ExpressApp.Blazor.SystemModule;
using DevExpress.ExpressApp.Tests.Blazor.Helpers;
using NUnit.Framework;

namespace DevExpress.ExpressApp.Tests.Blazor.SystemModule {
    [TestFixture]
    public class ModificationsControllerTests : BaseDBTest {
        [Test]
        public void TestUpdateActionState() {
            DetailView detailView = new TestDetailViewFactory(this).CreateView<TestPersistentObject>(true);
            BlazorModificationsController modificationsController = new BlazorModificationsController();
            modificationsController.SetView(detailView);
            Assert.IsTrue(modificationsController.SaveAction.Active["OnlyForDetailView"]);
            Assert.IsTrue(modificationsController.SaveAndCloseAction.Active["OnlyForDetailView"]);
            Assert.IsTrue(modificationsController.SaveAndNewAction.Active["OnlyForDetailView"]);
            Assert.IsTrue(modificationsController.CancelAction.Active["OnlyForDetailView"]);

            ListView listView = new TestListViewFactory(this).CreateView<TestPersistentObject>();
            modificationsController = new BlazorModificationsController();
            modificationsController.SetView(listView);
            Assert.IsFalse(modificationsController.SaveAction.Active["OnlyForDetailView"]);
            Assert.IsFalse(modificationsController.SaveAndCloseAction.Active["OnlyForDetailView"]);
            Assert.IsFalse(modificationsController.SaveAndNewAction.Active["OnlyForDetailView"]);
            Assert.IsFalse(modificationsController.CancelAction.Active["OnlyForDetailView"]);
        }
//...
}

2. Test whether a boolean property editor has localized values in the underlying control based on the Application Model.

//...
[Test]
public void SelectedItemTest() {
    ModelPropertyEditorImpl model = new ModelPropertyEditorImpl("Bool");
    model.CaptionForFalse = "CaptionForFalse";
    model.CaptionForTrue = "CaptionForTrue";
    BooleanPropertyEditor propertyEditor = new BooleanPropertyEditor(typeof(TestObjectWithNullableProperties), model);

    propertyEditor.ComponentValue = null;
    Assert.IsNull(propertyEditor.SelectedItem);
    Assert.IsNull(propertyEditor.ComponentValue);

    propertyEditor.ComponentValue = true;
    Assert.AreEqual(model.CaptionForTrue, propertyEditor.SelectedItem.Caption);
    Assert.AreEqual(propertyEditor.ComponentValue, propertyEditor.SelectedItem.Value);

    propertyEditor.ComponentValue = false;
    Assert.AreEqual(model.CaptionForFalse, propertyEditor.SelectedItem.Caption);
    Assert.AreEqual(propertyEditor.ComponentValue, propertyEditor.SelectedItem.Value);
}
//...

Future Plans

Ultimately, we will release all required assemblies with helper/mock classes (like TestDBTest, TestDetailViewFactory, BlazorAdapter, etc.) - all to reduce the time needed to write unit and functional tests with XAF.

If you have problematic scenarios that you want us to document, please leave comments to this post - thank you in advance.


Viewing all articles
Browse latest Browse all 148

Trending Articles