AL Runner

Migrating from version 2

Version 3 replaces version 2. Version 2 was written in C# on top of Business Central’s own compiler and runtime. Version 3 is written in Rust and reproduces what AL code can observe: values, errors, data, and the order of triggers and events. That is the public contract of the language, so it changes slowly and visibly. The version 2 engine is frozen on the v2 branch.

The NuGet package MSDyn365BC.AL.Runner stays and keeps getting updates. It becomes a wrapper around the version 3 engine, so you can keep installing with dotnet tool and run the new engine. The wrapper adds some start-up overhead, which should be small. Releases of the package that predate the wrapper still contain the version 2 engine and keep working.

If you maintain a tool that calls AL Runner, read Migrating tools from AL Runner v2 to v3.

What changes for you

Version 2Version 3
Installdotnet tool install -g MSDyn365BC.AL.Runner, needs the .NET SDKStandalone binary with no .NET: use mise or the install script. Or keep using dotnet tool, now a wrapper around the version 3 engine.
Commandal-runner [FLAGS] DIR...al-runner test [FLAGS] APP...
InputA “bundle” folderAn app folder, a source archive or an .app with source. Name the app and its test app.
Unsupported surfaceThe test fails with RunnerOutOfScopeExceptionThe test is not run, with a reason. Exit code 7.
Compile errorsExit code 3What cannot be compiled becomes “not run” rows. There is no exit code 3.
Test data--test-data, needs the bcbak readerOn by default with Microsoft’s apps. --no-test-data turns it off. No separate reader to install.
Failure textMay carry a .NET prefix such as NavNCLDialogException:The Business Central message only.
Stack traceA .NET stackThe AL call stack.
Timeout60 seconds of wall time20 seconds of CPU time.
Business Central versionsOne engine per minor versionOne binary for 27, 28 and 29.
DependenciesArtifact cache and dotnet tool store--dep, --package-cache, .alpackages, then the artifact feed.

Flags

Version 2Version 3
--test PATTERN, --filter PATTERNSame names. A pattern with a dot matches Codeunit<ID>.<Method>; without a dot it matches the method name.
--test-exact, --exclude-testSame.
--isolation codeunit|test|disabledcodeunit and test work. disabled is not supported.
--test-timeout SECONDSSame flag, now CPU time. Default 20.
--package-cache PATHSame.
--test-data, --test-data-companySame flags.
--output-junit PATH--junit FILE
--output-json--output-json [FILE], same shape. With no FILE it is the only thing on stdout.
--coverageSame, plus --coverage-out FILE and --coverage-json FILE.
--tddSame flag. Missing procedures and overloads are stubbed so far; missing fields, enum values and objects are not yet.
--serveral-runner serve, same protocol.
--define, --preprocessor-symbolsSame.
--countrySame.
--show-pass, --failures-only, --no-strict-exitNot accepted. Failures print by default; use --verbose for every test and --allow-not-run to relax exit codes.
--cache PATH, --no-cacheGone. Your own apps are compiled on every run. The dependency apps use the compile cache (--cache-dir).
--seed NNot accepted. Version 3 prints no seed.
--jobs NGone. Test codeunits run on worker threads automatically.
--watchNot available.
--dap [PORT]Not available yet.
--dump-csharp DIRGone. There is no C# stage.
--affected, --include-failing, --strict-environment, --per-suiteRefused with exit 2. --affected is planned.
--auto-provisionAccepted and ignored. Version 3 always downloads, unless --no-download.
--count-baseline, --expectationsGone.

The environment variables changed too. Version 3 uses ALRUNNER_CACHE as the one cache root, and the AL_RUNNER_ARTIFACTS_ROOT, _CACHE_ROOT, _SYMBOLS_ROOT and _ENGINE_CACHE_ROOT variables no longer apply. See the reference.

Exit codes

CodeVersion 2Version 3
0All passedAll passed
1A test failedA test failed
2A bundle could not executeBad invocation, or the run could not start
3A bundle could not compileNot used
4, 5Baseline and expectations mismatchesNot used
6The selection matched no testThe selection matched no test
7Not usedSome tests were not run
8Not usedNot run because the .NET helper could not be used

One difference with no workaround

Version 2 loaded compiled code. A dependency app that ships without AL source (a compiled-only app) could still run. Version 3 compiles everything from source and cannot run compiled C#. A test that reaches such an app is not run, and the message names the app. Provide an .app that carries its source, fake the dependency behind an interface, or keep using version 2 for that project.