-
Notifications
You must be signed in to change notification settings - Fork 1
Getting Started
Pixnop edited this page Jul 13, 2026
·
5 revisions
- A Vintage Story 1.21+ install (server or client, either works: Atlas only needs
VintagestoryAPI.dlland the game's own libraries). 1.21.0 is the floor since Atlas 0.9.0 (1.22.x and 1.21.7 are CI-verified on every push, 1.20.x works best effort); 1.19.x and older are rejected at boot. See Compatibility for the full per-version sweep results. - The
VINTAGE_STORYenvironment variable set to the folder containingVintagestoryAPI.dll. - .NET 10 SDK.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="xunit" Version="2.9.*" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageReference Include="Pixnop.Atlas.XUnit" Version="0.7.0" />
</ItemGroup>
<ItemGroup>
<!-- VintagestoryAPI is needed to compile game types (BlockPos and friends) that appear
directly in IWorldSession method signatures used in your scenario bodies. -->
<Reference Include="VintagestoryAPI">
<HintPath>$(VINTAGE_STORY)\VintagestoryAPI.dll</HintPath>
</Reference>
</ItemGroup>
</Project>Each piece matters:
- The
ReferencetoVintagestoryAPI.dllis required because game types appear directly inIWorldSessionmethod signatures, so the test project must compile against them. -
Pixnop.Atlas.XUnitshipsbuild/Atlas.E2E.targetsas abuildTransitiveMSBuild target (packed into the NuGet package itself, underbuildTransitive/Pixnop.Atlas.XUnit.targets). For package consumers, this means no manual<Import>is needed: the target runs automatically on every build and copies the game's ownNewtonsoft.Json.dllover whatever version the test SDK pulled in transitively. Skipping this fix does not fail the build; it fails at test run time instead, with a confusingMissingMethodException. See Troubleshooting.
Building from source instead
The manual <Import> path applies only to consumers building Atlas from source (a
ProjectReference to Atlas.XUnit.csproj rather than a PackageReference), where the
buildTransitive packaging step never runs:
<ItemGroup>
<Reference Include="VintagestoryAPI">
<HintPath>$(VINTAGE_STORY)\VintagestoryAPI.dll</HintPath>
</Reference>
<ProjectReference Include="path/to/Atlas.XUnit/Atlas.XUnit.csproj" />
</ItemGroup>
<!-- Only needed when building from source. Package consumers get this automatically. -->
<Import Project="path/to/build/Atlas.E2E.targets" />using Atlas.XUnit;
using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]
// Resolved relative to the test assembly's own output directory.
[assembly: AtlasMods("relative/path/to/your/mod")]-
DisableTestParallelizationis required: Atlas hosts at most one live server per process, so scenario classes cannot run concurrently. -
AtlasModsAttributepaths (folder,.zip, or.dll) are resolved relative to the test assembly's own output directory, not the source tree. See Mod Staging for the full path resolution rules and the MSBuildProjectReferencesugar that avoids hand-writing this path.
This one uses a vanilla block, so no mod is required to try Atlas out:
using Atlas.Api;
using Atlas.XUnit;
using Vintagestory.API.MathTools;
using Xunit;
public class MarkerScenarios : AtlasScenarioBase
{
[AtlasScenario]
public async Task Chest_Should_BePlaceable_When_WorldIsReady()
{
BlockPos pos = World.Spawn.Offset(1, 1, 0);
World.SetBlock("game:chest-east", pos);
await World.Ticks(5);
Assert.Equal("game:chest-east", World.BlockAt(pos).Code.ToString());
}
}dotnet testAtlas boots a fresh headless server per test class (superflat world, creative playstyle, fixed seed by default), pumps it on a dedicated game thread, runs your scenario on that thread, then tears it down.
See Writing Scenarios for the full attribute reference and authoring rules, CLI to run the compiled assembly without VSTest (including multi-process parallel execution), and Troubleshooting if something does not work as expected.