Skip to the content

News

Object types is case sensitive in TenantWebServiceCollection (1)

Last week while I was working on an integration project, I wanted to call a Business Central function from Azure Logic Apps. I had few options with APIs but I went ahead with creating a CodeUnit with a...
()

Object types is case sensitive in TenantWebServiceCollection (2)

Last week while I was working on an integration project, I wanted to call a Business Central function from Azure Logic Apps. I had few options with APIs but I went ahead with creating a CodeUnit with a...
()

Test Fixture Initializer

Overtime I have been advocating the use of the standard Business Central tests in various posts, webinars, conference presentations, and my . IMHO this has been, and still, is an undervalued collection of over 22,000 automated tests that cover all functional areas. It's a no brainer to let them run on your solution as . In case your solution intertwines with standard code chances are big that these tests will also hit your code resulting in a number of failing tests. As discussed in this this run resulted in over 75 % of failing tests when executed on our solution. Meaning that indeed the standard tests did hit our code and that we had a potential horizon of thousands of tests that could be running on our solution. After 6 weeks of work we had, on our NAV 2016 solution, a test collateral of more than 14,000 tests that was going to be run every night. A test run that each morning was going to show us the sanity of that part of our solution. Today, on NAV 2018, this collateral entails 18,300 tests, mainly standard. But we have meanwhile also been writing our own.

By mainly working on the of the tests we could raise the success rate from an initial 23 % to 72 % within one week of work. And eventually even more. Based on this work and some suggestions we also got a buy-in from Microsoft in improving their test code by adding publishers that would allow us to adjust standard tests with little to none footprint. The most import improvement was implemented by Microsoft in the Initialize function that the majority of standard tests hold to take care of the shared fixture or generic fresh fixture:

local procedure Initialize()
begin
    // Generic Fresh Setup
    LibraryTestInitialize.OnTestInitialize();
    //

    // Lazy Setup
    if isInitialized then
        exit();
    LibraryTestInitialize.OnBeforeTestSuiteInitialize();
    //

    isInitialized := true;
    Commit();
    LibraryTestInitialize.OnAfterTestSuiteInitialize();
end;

Using the now available publishers we built up code that I have now published on and have called the Test Fixture Initializer. To enable the creation of a shared fixture we subscribe to the OnBeforeTestSuiteInitialize publisher as it has proven to do this before any standard code does. To achieve the same for a generic fresh fixture we subscribe to the OnTestInitialize publisher. The OnAfterTestSuiteInitialize publisher will fire after standard code has done its part on he shared fixture. We have experienced that we hardly ever use this one, but of course you might if your code needs extend the shared fixture after everything else and/or needs to happen after the Commit.

The following schema shows how the code is structured:

OnTestInitialize

At this level you will be adding code for each specific standard test codeunit in SetGenericFreshSetup in Codeunit 97004 (FLX Generic Fresh Setup) to get generic fresh fixture created:

Codeunit 97004 "FLX Generic Fresh Setup"
{
    // (c) fluxxus.nl

    procedure SetGenericFreshSetup(CallerCodeunitID: Integer)
    begin
        case CallerCodeunitID of
            Codeunit::"ERM Sales Batch Posting": // please be sure only to remove this example codeunit if not relevant to you
                SetGenericFreshSetupForERMSalesBatchPosting();
        // add specific codeunits and your method to set generic fresh fixture here
        end
    end;

    local procedure SetGenericFreshSetupForERMSalesBatchPosting()
    begin
    end;
}

OnBeforeTestSuiteInitialize

At this level you will be adding each specific standard test codeunit to the case statement in  DoesCodeunitNeedLazySetup function in Codeunit 97005 (FLX Check Lazy Setup) to get standard shared fixture created for it by the Initialize function in Codeunit 97000 (FLX Initialize):

Codeunit 97005 "FLX Check Lazy Setup"
{
    // (c) fluxxus.nl

    procedure DoesCodeunitNeedLazySetup(CallerCodeunitID: Integer): Boolean
    begin
        case CallerCodeunitID of
            // add specific codeunits here that need additonal shared fixture
            Codeunit::"Purch. Document Posting Errors": // please be sure only to remove this example codeunit if not relevant to you
                exit(true);
            else
                exit(false);
        end;
    end;
}

If a standard codeunit needs some specific, i.e. additional, shared fixture add the codeunit to the case statement in SetAdditionalLazySetupBefore in Codeunit 97007 (FLX Additional Lazy Setup):

Codeunit 97007 "FLX Additional Lazy Setup"
{
    // (c) fluxxus.nl

    procedure SetAdditionalLazySetupBefore(CallerCodeunitID: Integer)
    begin
        case CallerCodeunitID of
            Codeunit::"ERM Edit Posting Groups": // please be sure only to remove this example codeunit if not relevant to you
                SetAdditonalLazySetupBeforeForERMEditPostingGroups();
        // add specific codeunits and your method to set additonal shared fixture here
        end
    end;

    local procedure SetAdditonalLazySetupBeforeForERMEditPostingGroups()
    begin
    end;
}

Initialize

The spill of the Test Fixture Initializer is the Initialize function in Codeunit 97000 (FLX Initialize). This is were you will need to add various functions that do create the data (or update existing CRONUS data). The next code example is an excerpt from the Initialize for our solution:

procedure Initialize()
begin
    if not DoesPrebuiltFixtureExist thn
    begin
        SetPrebuiltFixtureExists(true);

        N4LibraryLabel.CreateLabels;
        N4LibrarySetup.CreateTNTSetups;
        N4LibrarySetup.SetCompanyInformation;
        N4LibrarySetup.SetWarehouseSetup;
        N4LibrarySetup.SetInventorySetup;
        N4LibraryERM.CreateVATPostingSetups;
        N4LibraryERM.UpdateVATProdPostingGroups;
        N4LibrarySetup.SetPurchaseSetup;
        N4LibrarySetup.CreateSalesSetups;
        N4LibrarySetup.SetSalesSetups;
        N4LibrarySetup.CreateVDESetups;
        N4LibrarySetup.CreateOWSSetups;
        N4LibrarySetup.CreateOWSCommunicationSetups;
        N4LibrarySetup.CreateCBSetups;
        N4LibrarySetup.CreateOWSNumbersSetups;
        N4LibrarySetup.CreateMultiple3SNoSeries;
        N4LibrarySetup.CreateTransactionModes;
        N4LibrarySetup.CreateMultiplePaymentTerms;
        N4LibrarySetup.CreateTermPeriodDefinitions;
        N4LibrarySetup.CreateOWSSelections;
        N4LibrarySetup.CreateReqWorksheetTemplates;
        N4LibrarySetup.UpdateCustomerTemplates('STS');
        N4LibrarySetup.UpdateCustomers('STS');
        N4LibrarySetup.CreateDeliverabilityCodes;
        N4LibrarySetup.UpdateSalesDocuments('STS');
        N4LibrarySetup.UpdateItems;
    end;
end;

Initialize Prebuilt Fixture

As some of you probably know I am a huge fan of not wanting to have a prebuilt fixture. I want my test code to control and create the fixture needed so it is independent of the setting it will run in. Nevertheless, as you can see the Test Fixture Initializer project has enabled with Codeunit 97008 (FLX Initialize Preb. Fixture) to run the Initialize function in Codeunit 97000 (FLX Initialize). This is what we do before a newly created test suite will be run, as this shortens the total time of the test run. For that reason the Test Setup table has been added to the project, so that Prebuilt Fixture Exists field  can be check marked once the prebuilt fixture has been created. Any time the Initialize function is to be called this field will be verified whether or not the prebuilt fixture already exists.

Hope this all makes sense and will help in getting the standard test added to your test collateral. Feel free to make use of the code, and share your suggestions for improvements be means of an issue report.

DevOps Build Agents for Microsoft Dynamics 365 Business Central

Not too long ago, I did a webinar for ALOps.  The idea of these webinars is simple: how can you get started with DevOps for Microsoft Dynamics 365 Business Central.  And I’m not going to lie: I will focus on doing that with ALOps.  But that’s not the only focus of these videos – I …

Directions ASIA Postponed

The Directions 4 Partners Committee has been continuously monitoring the coronavirus (COVID-19) outbreak in relation to Directions ASIA, April 2-3, in Bangkok. The health and safety of our community is and always will be our main priority. That's why we have decided to reschedule Directions ASIA 2020 to the second half of the year.  We are still working very hard on confirming new dates at the same venue and will communicate them shortly. 

“How-to” use the restored Business Central SaaS database on On-premise environment – Part II

“How-to” use the restored Business Central SaaS database on On-premise environment – Part II Some have written to me about

Searching the unsearchable, episode 2

True, there was no episode 1, not on this blog. But if Star Wars can start with episode 4, I don’t see why can’t I start with episode 2. Especially when Waldo has already written…

The post appeared first on .

Codeunit API’s in Business Central

This blog post was on my list way too long… But now I found some time to sit down and write it. Disclaimer What I’m going to show here is officially not supported (yet). It is an undocumented feature that ...

Searching the unsearchable

You probably know about the twitter hashtag “bcalhelp” .. A way for you to ask help on twitter about anything AL for Microsoft Dynamics 365 Business Central. Well – yesterday, it made me smile … there was someone that was trying to find something on Vjeko’s blog.  Pretty clever to use the bcalhelp for it …

Using tables instead of table extensions

Recently James Crowter wrote an excellent article about table extensions and how they affect performance. In short, table extensions are great for flexibility and ease of development, but performance decreases when the number of table extensions is adding up. Especially ...