Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
5288857
Enhance SkyrimSE and Fallout4 path handling, add `Preferences` locati…
halgari Oct 2, 2025
482f938
Introduce plugin load order handling for Skyrim SE
halgari Oct 2, 2025
c480b22
Refactor plugin load order handling and streamline sorting logic
halgari Oct 6, 2025
87dca4d
Switch LEFT JOINs to INNER JOINs in Synchronizer queries and update i…
halgari Oct 6, 2025
01d1f3a
Comment out untestable code in `Ingest` method and add placeholder im…
halgari Oct 6, 2025
3487a6a
Add integration tests for Skyrim SE plugin load order and refine SQL …
halgari Oct 7, 2025
bc9560b
Implement steam CLI verb for creating depot images
halgari Oct 8, 2025
87fe348
Remove `ChunkedStream` and `IChunkedStreamSource`, add integration te…
halgari Oct 9, 2025
af30050
First integration test passes
halgari Oct 13, 2025
33686a4
Improve game file validation for integration tests, add missing game …
halgari Oct 13, 2025
a61b664
Add `steam manifest pack-game` CLI verb to pack Steam manifests into …
halgari Oct 13, 2025
c04d95e
Refactor manifest processing by introducing `TryResolveManifest` and …
halgari Oct 13, 2025
22ccfb0
Expose `GameImagesEnvVarName` as a constant, improve integration test…
halgari Oct 13, 2025
7f0d50c
Add GitHub Actions workflow for running integration tests
halgari Oct 13, 2025
79b5c7a
Fix the actions runner
halgari Oct 13, 2025
bd37113
Improve SkyrimSE path resolution by adding OS-specific Steam folder m…
halgari Oct 13, 2025
ab2553e
Inline parts of the test workflow so that we no longer run integratio…
halgari Oct 13, 2025
d79ed6a
Merge branch 'main' into game-integration-tests
halgari Oct 13, 2025
aa29799
Fixup some broken namespaces, merge main
halgari Oct 13, 2025
6e44d28
Update networking test workflow to exclude integration projects and i…
halgari Oct 13, 2025
8c12b50
Add PowerShell installation step for Linux in test workflow
halgari Oct 13, 2025
6e81325
Add PowerShell installation step to networking test workflow for Linux
halgari Oct 13, 2025
aea96aa
Simplify test workflows by removing PowerShell installation on Linux,…
halgari Oct 13, 2025
39287c7
Try a different approach for filtering integration tests,
halgari Oct 14, 2025
0b86570
Clean up how we generate test cases for integration tests, disable te…
halgari Oct 14, 2025
7a107d8
Update environment variable usage in integration tests to improve cla…
halgari Oct 14, 2025
b2cc547
Update documentation for running and creating integration tests, clar…
halgari Oct 14, 2025
9fd6bc4
Merge branch 'main' into game-integration-tests
halgari Oct 14, 2025
18dcf5d
Refactor loadout creation in `AGameIntegrationTest` to use `ILoadoutM…
halgari Oct 14, 2025
18aecfc
Improve test workflows and logic for integration tests
halgari Oct 14, 2025
e698c8e
Add dummy test to prevent framework errors when no tests are found
halgari Oct 14, 2025
f04f36c
Merge ingegration tests (and main)
halgari Oct 14, 2025
4f3c6e6
WIP porting collection tests over to integration tests
halgari Oct 14, 2025
78123f0
Porting CE tests over to integration tests
halgari Oct 14, 2025
bb41f7e
Add verification files for `LibraryArchiveInstallerTests` test cases
halgari Oct 15, 2025
86cb029
Add new verification files for `LibraryArchiveInstallerTests` in Skyr…
halgari Oct 15, 2025
f3105ab
Remove outdated `PluginLoadOrderIntegrationTests` and add new verific…
halgari Oct 15, 2025
bf1d24a
Update schema verification for `SchemaVersions` tests to include new …
halgari Oct 15, 2025
67c7323
Add support for plugin sort order varieties in Fallout 4
halgari Oct 15, 2025
71c6c0c
Update the test suite to run on self-hosted runners
halgari Oct 22, 2025
837869e
Remove the old test runners
halgari Oct 22, 2025
4a4d83f
merge the integration test code
halgari Oct 22, 2025
0181408
Normalize casing for `runs_on` labels in GitHub Actions workflow defi…
halgari Oct 22, 2025
765513c
Remove unnecessary .NET setup step from GitHub Actions workflow
halgari Oct 22, 2025
5d81c31
Remove unused `Startup` class from CreationEngine tests and switch to…
halgari Oct 22, 2025
906d0a5
pull in the Nexus API key
halgari Oct 22, 2025
46a7590
Fix the UI tests crashing on startup
halgari Oct 22, 2025
1c007dc
Merge remote-tracking branch 'origin/creation-loadorder' into creatio…
halgari Oct 22, 2025
c0e9cce
Update schema verification file with new attributes and namespaces
halgari Oct 22, 2025
1d12c50
Merge in main
halgari Oct 22, 2025
0993725
Update src/NexusMods.Games.CreationEngine/LoadOrder/PluginLoadOrderVa…
halgari Oct 22, 2025
d809da6
Disable a flakey GC test
halgari Oct 22, 2025
afeedbe
Merge remote-tracking branch 'origin/creation-loadorder' into creatio…
halgari Oct 22, 2025
ae2ed97
Merge branch 'main' into creation-loadorder
halgari Oct 29, 2025
d1a7d3b
Fix tests (locally)
halgari Oct 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions .github/workflows/clean_environment_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,30 @@ jobs:
run: exit 1

build-and-test:
strategy:
fail-fast: false
matrix:
include:
- os_name: linux
runs_on: [ self-hosted, Linux, x64 ]
shell: bash
- os_name: windows
runs_on: [ self-hosted, Windows, x64 ]
shell: powershell
runs-on: ${{ matrix.runs_on }}
if: github.event_name == 'push' || github.event.pull_request.draft == false
uses: Nexus-Mods/NexusMods.App.Meta/.github/workflows/dotnet-build-and-test-with-osx.yaml@main
with:
extra-test-args: "--blame-hang-timeout 20m"
test-filter: "RequiresNetworking!=True&FlakeyTest!=True"
codecov-flags: ",clean_environment_tests"

env:
NEXUS_API_KEY: ${{ secrets.NEXUS_API_KEY }}

steps:
- uses: actions/checkout@v4

- name: Restore
run: dotnet restore

- name: Build
run: dotnet build --configuration Release --no-restore

- name: Test
run: dotnet test --configuration Release --no-build --verbosity normal
37 changes: 0 additions & 37 deletions .github/workflows/networking_tests.yaml

This file was deleted.

11 changes: 6 additions & 5 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
<PackageVersion Include="NexusMods.MnemonicDB.Abstractions" Version="0.28.2" />
<PackageVersion Include="NexusMods.Hashing.xxHash3.Paths" Version="3.0.4" />
<PackageVersion Include="NexusMods.Hashing.xxHash3" Version="3.0.4" />
<PackageVersion Include="NexusMods.Archives.Nx" Version="0.6.4" />
<PackageVersion Include="NexusMods.Paths" Version="0.20.0" />
<PackageVersion Include="NexusMods.Paths.Extensions.Nx" Version="0.20.0" />
<PackageVersion Include="NexusMods.Paths.TestingHelpers" Version="0.20.0" />
<PackageVersion Include="NexusMods.Archives.Nx" Version="0.6.5" />
<PackageVersion Include="NexusMods.Paths" Version="0.22.5" />
<PackageVersion Include="NexusMods.Paths.Extensions.Nx" Version="0.22.5" />
<PackageVersion Include="NexusMods.Paths.TestingHelpers" Version="0.22.5" />
<PackageVersion Include="NexusMods.Telemetry.OpenTelemetry" Version="1.0.0" />
<PackageVersion Include="FomodInstaller.Interface" Version="1.2.0" />
<PackageVersion Include="FomodInstaller.Scripting.XmlScript" Version="1.0.0" />
Expand Down Expand Up @@ -56,6 +56,7 @@
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0" />
<PackageVersion Include="Polly.Core" Version="8.6.3" />
<PackageVersion Include="Polly" Version="8.6.3" />
<PackageVersion Include="TUnit.Core" Version="0.57.24" />
<PackageVersion Include="Verify" Version="30.11.0" />
<PackageVersion Include="Verify.TUnit" Version="30.11.0" />
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
Expand Down Expand Up @@ -163,4 +164,4 @@
<PackageVersion Include="TransparentValueObjects" Version="1.1.0" />
<PackageVersion Include="TransparentValueObjects.Abstractions" Version="1.1.0" />
</ItemGroup>
</Project>
</Project>
7 changes: 7 additions & 0 deletions NexusMods.App.sln
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NexusMods.Games.CreationEng
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NexusMods.Backend.Tests", "tests\NexusMods.Backend.Tests\NexusMods.Backend.Tests.csproj", "{9BA054EF-E912-49AB-8889-AE807713BD74}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NexusMods.Games.IntegrationTestFramework", "tests\Games\NexusMods.Games.IntegrationTestFramework\NexusMods.Games.IntegrationTestFramework.csproj", "{87664A03-EFA8-41C5-9407-E8E0E45402F6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -672,6 +674,10 @@ Global
{9BA054EF-E912-49AB-8889-AE807713BD74}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9BA054EF-E912-49AB-8889-AE807713BD74}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9BA054EF-E912-49AB-8889-AE807713BD74}.Release|Any CPU.Build.0 = Release|Any CPU
{87664A03-EFA8-41C5-9407-E8E0E45402F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{87664A03-EFA8-41C5-9407-E8E0E45402F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{87664A03-EFA8-41C5-9407-E8E0E45402F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{87664A03-EFA8-41C5-9407-E8E0E45402F6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -791,6 +797,7 @@ Global
{B7A8F2D3-1C4E-4F6B-9A2D-E5B6C7D8F9A0} = {52AF9D62-7D5B-4AD0-BA12-86F2AA67428B}
{8E8D0E1E-598D-459C-8624-DA1F8F4127D3} = {05B06AC1-7F2B-492F-983E-5BC63CDBF20D}
{9BA054EF-E912-49AB-8889-AE807713BD74} = {52AF9D62-7D5B-4AD0-BA12-86F2AA67428B}
{87664A03-EFA8-41C5-9407-E8E0E45402F6} = {05B06AC1-7F2B-492F-983E-5BC63CDBF20D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9F9F8352-34DD-42C0-8564-EE9AF34A3501}
Expand Down
38 changes: 38 additions & 0 deletions docs/developers/development-guidelines/RunningIntegrationTests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Running Integration Tests

The Nexus Mods app has certain tests marked as "integration tests", these are tests that require a valid copy of a game
in order to perform certain tests. These tests are separate from unit tests that attempt to mock various parts of the game
or introduce "fake game" data for testing.

## Overview

The integration tests run by storing copies of game files in `.nx` archives hosted in a "game images" folder. This folder
has the structure of `{root}/{Store}/{LocatorId}.nx`. So for steam these files are in `{root}/Steam/1234567890.nx` for Manifest ID
`1234567890`.

During tests a custom `IFileSystem` is created that uses these game images as a base, and stores any modified files in memory,
each test is then given a clean copy of the game files. Each test can run whatever operations it needs to run, and then
validate behavior against actual game files. Since NMA uses this `IFileSystem` abstraction across the entire app, it is possible
to use these game images as-is without extracting any files to disk. Tests can even be created to simulate a disk state
that does not match the reported Steam state.

## Setup
In order to run the integration tests for a given game you must first create the game images. For steam this is done by
running the CLI command `steam manifest pack-game -a "{Game Name}" -o "{ImagesRoot}"`. Note that "Game Name" is the english
name of the game, such as "Skyrim Special Edition". The output folder is the base folder, not the Steam sub-folder. This
CLI command will download all the manifests for the given game and pack the game files into `.nx` archives. Next you must
specify the root folder for tests, via the environment variable `NMA_INTEGRATION_BASE_PATH` environment variable.

## Running Tests

Now simply navigate to a specific integration test folder and run `dotnet run` to run the tests via tUnit. The Integration tests
will not run at all if the environment variable `NMA_INTEGRATION_BASE_PATH` is not set, and will error if the correct game
images are not present. This silent failure with the environment variable is intentional, so that CI runs in various environments
without failures and without having specify complex filters in the test runners. The NMA project hosts all tgame images
on the test runner for the integration tests, speak with the app developers if there are additional manifests requried for testing.

## Create new tests
To create new tests, create a class that inherits from `AGameIntegrationTest`. Specify which games to run the test on
via attributes attached to the class. These attributes then generate data that is used to parameterize the test. Be liberal
with the creation of new test attributes, as they are an easy extension point for creating new inputs and for verifying
behavior across multiple games and platforms.
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,11 @@ public IReadOnlyCollection<LocationId> GetNestedLocations(LocationId id)
/// <returns></returns>
public GamePath ToGamePath(AbsolutePath absolutePath)
{
absolutePath = absolutePath.FileSystem.Unmap(absolutePath);
return _locations.Values.Where(location => absolutePath.StartsWith(location.ResolvedPath))
.Select(desc => new GamePath(desc.Id, absolutePath.RelativeTo(desc.ResolvedPath)))
.MinBy(gamePath => gamePath.Path.Path.Length);

}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Diagnostics;
using System.IO.Compression;
using System.IO.Hashing;
using System.Runtime.InteropServices;
using System.Text;
Expand All @@ -8,6 +9,7 @@
using NexusMods.FileExtractor;
using NexusMods.Paths;
using NexusMods.Sdk.IO;
using ZipFile = ICSharpCode.SharpZipLib.Zip.ZipFile;

namespace NexusMods.Backend.FileExtractor.Extractors;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public SevenZipExtractor(
_temporaryFileManager = fileTemporaryFileManager;
_processRunner = processRunner;
_osInformation = osInformation;

_exePath = GetExtractorExecutable(fileSystem, osInformation);
logger.LogDebug("Using extractor at {ExtractorExecutable}", _exePath);
}
Expand Down Expand Up @@ -182,6 +182,7 @@ internal static void To7ZipWindowsExtractionPath(Span<char> input)
{
var pathsWithInvalidCharacters = new List<(string fileName, bool isDirectory)>();

source = source.FileSystem.Map(source);
// NOTE(erri120): "l -ba" is an undocumented command that skips the table header and footer
var process = Cli
.Wrap(_exePath)
Expand Down Expand Up @@ -242,6 +243,8 @@ internal static bool TryParseListCommandOutput(ReadOnlySpan<char> line, [NotNull

private async ValueTask ExtractArchive(AbsolutePath source, AbsolutePath destination, CancellationToken cancellationToken)
{
destination = destination.FileSystem.Map(destination);
source = source.FileSystem.Map(source);
// NOTE(erri120): Using "-bsp1" to redirect the progress line to stdout
var process = Cli
.Wrap(_exePath)
Expand Down
1 change: 1 addition & 0 deletions src/NexusMods.Backend/FileExtractor/FileExtractor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public async Task ExtractAllAsync(IStreamFactory sFn, AbsolutePath dest, Cancell
catch (Exception ex)
{
_logger.LogError(ex, "While extracting via {Extractor}", extractor);
throw;
}
}

Expand Down
Loading
Loading