Portamical.Core 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Portamical.Core --version 1.0.0
                    
NuGet\Install-Package Portamical.Core -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Portamical.Core" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Portamical.Core" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Portamical.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Portamical.Core --version 1.0.0
                    
#r "nuget: Portamical.Core, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Portamical.Core@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Portamical.Core&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Portamical.Core&version=1.0.0
                    
Install as a Cake Tool

Portamical

A Universal, Identity-Driven Test Data Modeling Framework for .NET

License: MIT .NET 10 C# Stars

Write test data once. Run it on xUnit v2, xUnit v3, MSTest 4, and NUnit 4β€”without rewriting tests or losing strong typing.

Portamical is the test data abstraction layer missing from the .NET testing ecosystem. It treats test data as first-class domain objects with deterministic identity, enabling automatic deduplication, cross-framework portability, and self-documenting test output.


The Problem It Solves

Traditional Approach Portamical Approach
πŸ”΄ Duplicate test data per framework βœ… Write once, consume everywhere
πŸ”΄ Fragile object[] arrays βœ… Strongly typed generics (up to 9 args)
πŸ”΄ Cryptic test names in runners βœ… Human-readable "definition β‡’ result"
πŸ”΄ Duplicate test cases slip through βœ… Built-in identity-based deduplication
πŸ”΄ Exception assertions differ by framework βœ… Unified PortamicalAssert with delegate injection
πŸ”΄ Boilerplate test data setup βœ… TestDataFactory with fluent creation
πŸ”΄ Mutable test state βœ… init-only properties throughout

Quick Start

1. Clone and Build

git clone https://github.com/CsabaDu/Portamical.git
cd Portamical
dotnet build
dotnet test

2. Choose Your Framework Solution

Framework Solution File
Core Library Portamical.Core.slnx
Shared Layer Portamical.slnx
xUnit v2 Portamical.xUnit.slnx
xUnit v3 Portamical.xUnit_v3.slnx
MSTest 4 Portamical.MSTest.slnx
NUnit 4 Portamical.NUnit.slnx

3. Create Your First Data Source

using static Portamical.Core.Factories.TestDataFactory;

// Identity‑driven test cases with deterministic naming
public class EmailValidationCases
{
    public IEnumerable<TestData<string>> GetValidArgs()
    {
        // Each test case defines:
        // - a human‑readable identity ("definition")
        // - the expected outcome ("result")
        // - the argument sequence (arg1, arg2, ...)
        yield return CreateTestData(
            definition: "input is a valid email",
            result: "validates successfully",
            arg1: "user@example.com");

        yield return CreateTestData(
            definition = "input is a valid name",
            result = "validates successfully",
            arg1 = "John Doe");
    }
}

Power users can combine specialized test‑data types with local helper functions to keep factory calls consistent, expressive, and invariant‑safe:

public class AdvancedEmailValidationCases
{
    public IEnumerable<TestData<string>> ValidEmails()
    {
        // Local helper:
        // - Centralizes the factory call shape
        // - Ensures argument ordering stays invariant across all yields
        // - Makes edits safer: update the variables once, keep call sites unchanged
        TestDataReturns<bool, string> createTestData()
            => CreateTestDataReturns(
                definition: definition,
                expected: expected,
                arg1: email);

        // First case
        string definition = "input is a valid email";
        bool expected = true;
        string email = "user@example.com";
        yield return createTestData();

        // Reassign the same variables for the next identity
        definition = "input is a valid email with subdomain";
        expected = true;
        email = "john.doe@mail.example.com";
        yield return createTestData();
    }
}

4. Consume Across All Frameworks

// xUnit v2/v3
[Theory, MemberData(nameof(Args))]
public void Validate_validInput_returnsTrue(TestData<string> testData) 
{
    var actual = Validate(testData.Arg1);
    Assert.True(actual);
}

// MSTest
[TestMethod, DynamicData(nameof(Args))]
public void Validate_validInput_returnsTrue(TestData<string> testData) 
{
    var actual = Validate(testData.Arg1);
    Assert.IsTrue(actual);
}

// NUnit
[Test, TestCaseSource(nameof(Args))]
public void Validate_validInput_returnsTrue(TestData<string> testData) 
{
    var actual = Validate(testData.Arg1);
    Assert.That(actual, Is.True);
}

Architecture

Layered Design (Zero-Dependency Core)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚            _SampleCodes                        β”‚  ← Reference implementations
β”‚  (Testables, DataSources, UnitTests)           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚ depends on
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Portamical.xUnit | xUnit_v3 | MSTest | NUnit  β”‚  ← Framework adapters
β”‚          (Thin adapter layer)                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚ depends on
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              Portamical                        β”‚  ← Shared utilities
β”‚  (Converters, Assertions, TestBases)           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚ depends on
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚          Portamical.Core                       β”‚  ← Pure abstractions
β”‚  (Interfaces, Models, Factory β€” ZERO DEPS)     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Namespace Dependency Diagram:

Portamical_Namespaces_Hierarchy


Class Hierarchy (Template Method + Composite)

NamedCase (abstract) : INamedCase : IEquatable<INamedCase>
 └── TestDataBase (abstract) : ITestData
      β”œβ”€β”€ TestData<T1..T9> (abstract)
      β”‚    └── [T4-generated: TestData<T1> β†’ ... β†’ TestData<T1,...,T9>]
      └── TestDataExpected<TResult> (abstract) : IExpected<TResult>
           β”œβ”€β”€ TestDataReturns<TStruct> : IReturns<TStruct>
           β”‚    └── [T4-generated: TestDataReturns<TStruct,T1> β†’ ... β†’ <TStruct,T1,...,T9>]
           └── TestDataThrows<TException> : IThrows<TException>
                └── [T4-generated: TestDataThrows<TException,T1> β†’ ... β†’ <TException,T1,...,T9>]

Key: T4 code generation eliminates 27 classes worth of boilerplate while maintaining type safety.


Core Innovation: Identity-Driven Test Cases

Every test case is an immutable value object with deterministic identity:

"<definition> => <result>"

Real Examples from the Codebase

Test Case Identity
"Valid name and dateOfBirth is equal with the current day => creates BirthDay instance"
"name is null => throws ArgumentNullException"
"other is null => returns -1"

What This Enables

  1. Automatic Deduplication

    // Built into TheoryTestData<TTestData>
    private readonly HashSet<INamedCase> _namedCases = new(NamedCase.Comparer);
    
    public override void Add(ITheoryTestDataRow row)
    {
        if (_namedCases.Add(row))  // ← Identity-based add
        {
            base.Add(row);
        }
    }
    
  2. Self-Documenting Test Output

    • Test runners display: "input is valid email => validates successfully"
    • No manual [Trait], [TestName], or DisplayName attributes needed
  3. Cross-Framework Consistency

    • Same identity regardless of xUnit, MSTest, or NUnit
    • Enables traceability from requirement β†’ test data β†’ execution
  4. Value-Based Equality

    public static IEqualityComparer<INamedCase> Comparer { get; } =
        new NamedCaseEqualityComparer();
    
    public bool Equals(INamedCase? x, INamedCase? y)
    => StringComparer.Ordinal.Equals(x.TestCaseName, y.TestCaseName);
    

Test Data Types

Universal Test Data Model

Type Purpose Constraints Use Case
TestData<T1..T9> General scenarios Up to 9 arguments Constructor tests, basic behavior
TestDataReturns<TStruct, T1..T9> Return-value assertions TStruct : struct Method output validation
TestDataThrows<TException, T1..T9> Exception assertions TException : Exception Error handling tests

Factory Pattern (T4-Generated)

using static Portamical.Core.Factories.TestDataFactory;

// General test data
yield return CreateTestData(
    definition: "Valid input",
    result: "creates instance",
    arg1: "valid name",
    arg2: DateOnly.FromDateTime(DateTime.Now));

// Return-value test data
yield return CreateTestDataReturns(
    definition: "other is null",
    expected: -1,  // ← TStruct (value type)
    arg1: dateOfBirth,
    arg2: (BirthDay?)null);

// Exception test data
yield return CreateTestDataThrows(
    definition: "name is null",
    expected: new ArgumentNullException("name"),
    arg1: (string?)null);

Key: Factory methods are T4-generated from a single source (SharedHelpers.ttinclude). Change MaxArity = 9 to support more arguments, regenerate, and build.


Data Strategy Pattern

The Strategy Pattern (ArgsCode + PropsCode) controls how test data materializes into framework-consumable rows.

Strategy Modes

1. TestData Mode (Direct Instance Flow)
// Data source
public static IEnumerable<TTestData> Data => Convert(dataSource.GetArgs());

// Test signature
void Test(TestData<DateOnly> testData) { ... }
2. Instance Mode (ArgsCode.Instance)
// Data source
public static IEnumerable<object?[]> Data => Convert(dataSource.GetArgs());

// Test signature (same as TestData mode)
void Test(TestData<DateOnly> testData) { ... }
3. Properties Mode (ArgsCode.Properties)
// Data source
public static IEnumerable<object?[]> Data 
    => Convert(dataSource.GetArgs(), AsProperties);

// Test signature (flattened parameters)
void Test(DateOnly dateOfBirth) { ... }

PropsCode Options

PropsCode Includes Use Case
All TestCaseName + all properties MSTest with DynamicDataDisplayName
TrimTestCaseName All properties except TestCaseName Default β€” test runner provides naming
TrimReturnsExpected Also excludes Expected if IReturns NUnit return-value tests
TrimThrowsExpected Also excludes Expected if IThrows Exception tests where assertion extracts exception

Design Patterns Catalog

Portamical implements 15 GoF and architectural patterns to achieve portability and maintainability.

Pattern Implementation Purpose
Factory TestDataFactory (T4-generated) Centralized test data creation
Builder Named parameters in factory methods Fluent, self-documenting API
Adapter Framework-specific adapters Translate ITestData to framework types
Strategy ArgsCode + PropsCode enums Configurable data serialization
Template Method TestDataBase.ToArgs() Skeleton algorithm with hooks
Composite Test data hierarchy Uniform treatment of test data
Command Delegate injection in PortamicalAssert Framework-agnostic assertions
Iterator IEnumerable<TTestData> Lazy test data evaluation
Null Object Optional testMethodName Eliminate null checks
Identity NamedCase.Comparer Value object with deterministic identity
Dependency Inversion Layered architecture Core has zero dependencies
Repository Data sources Centralized test data storage
Code Generation T4 templates Single source of truth (MaxArity)
Local Method Pattern static local functions Encapsulated helpers, zero closure cost
Bridge Core ↔ Adapters Decouple abstraction from implementation

Full Pattern Analysis


T4 Code Generation

How It Works

All generic test data classes and the factory are generated at design time by T4 templates.

Portamical.Core/
β”œβ”€β”€ T4/
β”‚   └── SharedHelpers.ttinclude        ← Single source of truth (MaxArity = 9)
β”œβ”€β”€ Factories/
β”‚   β”œβ”€β”€ TestDataFactory.tt             ← Template
β”‚   └── TestDataFactory.generated.cs   ← Auto-generated output (736 lines)
└── TestDataTypes/Models/
    β”œβ”€β”€ General/
    β”‚   β”œβ”€β”€ TestData.tt                ← Template
    β”‚   └── TestData.generated.cs      ← Auto-generated output
    └── Specialized/
        β”œβ”€β”€ TestDataReturns.tt         ← Template
        β”œβ”€β”€ TestDataReturns.generated.cs
        β”œβ”€β”€ TestDataThrows.tt          ← Template
        └── TestDataThrows.generated.cs

Centralized Configuration

All four templates share a single SharedHelpers.ttinclude file:

// Portamical.Core/T4/SharedHelpers.ttinclude
const int MaxArity = 9;  // ← Change once, regenerate all

Regeneration Process

# 1. Edit SharedHelpers.ttinclude β†’ change MaxArity
vim Portamical.Core/T4/SharedHelpers.ttinclude

# 2. In Visual Studio: select all 4 .tt files
# 3. Right-click β†’ Run Custom Tool

# 4. Build
dotnet build

Design Decisions

Template Pattern Include Placement Rationale
TestData.tt Inline text output End of file Extra trailing newline is harmless
TestDataReturns.tt Inline text output End of file Same
TestDataThrows.tt Inline text output End of file Same
TestDataFactory.tt StringBuilder Joined before line 5 Prevents CS8802 (second compilation unit)

Note: The .generated.cs files are checked into source control so the solution builds without running T4 transformations.


Framework Adapters

Thin, optional adapters bridge Portamical to each test runner:

Project Framework Key Integration
Portamical.xUnit xUnit v2 TheoryData<T> via ToTheoryData()
Portamical.xUnit_v3 xUnit v3 (3.2.2+) MemberTestDataAttribute, ITheoryTestDataRow
Portamical.MSTest MSTest 4 (4.0.2+) DynamicTestDataAttribute
Portamical.NUnit NUnit 4 (4.4.0+) TestCaseDataSourceAttribute, TestCaseTestData

Same Data Source, Four Frameworks

// Shared β€” works everywhere
private static readonly BirthDayDataSource _dataSource = new();

// xUnit v2 / v3
public static IEnumerable<object?[]> Args => Convert(_dataSource.GetConstructorValidArgs());
[Theory, MemberData(nameof(Args))]

// MSTest
private static IEnumerable<object?[]> Args => Convert(_dataSource.GetConstructorValidArgs());
[TestMethod, DynamicData(nameof(Args))]

// NUnit
public static IEnumerable<object?[]> Args => Convert(_dataSource.GetConstructorValidArgs(), AsInstance);
[Test, TestCaseSource(nameof(Args))]

Unified Exception Assertions

PortamicalAssert.ThrowsDetails validates exception type, message, and parameter name using delegate injection (Command Pattern):

// xUnit
PortamicalAssert.ThrowsDetails(attempt, expected,
    catchException: Record.Exception,
    assertIsType: Assert.IsType,
    assertEquality: Assert.Equal,
    assertFail: Assert.Fail);

// NUnit
PortamicalAssert.ThrowsDetails(attempt, expected,
    catchException: CatchException,
    assertIsType: (e, a) => Assert.That(a, Is.TypeOf(e)),
    assertEquality: (e, a) => Assert.That(a, Is.EqualTo(e)),
    assertFail: Assert.Fail);

// MSTest
PortamicalAssert.ThrowsDetails(attempt, expected,
    catchException: CatchException,
    assertIsType: (e, a) => Assert.AreEqual(e, a.GetType()),
    assertEquality: (e, a) => Assert.AreEqual(e, a),
    assertFail: Assert.Fail);

Key: Framework-specific assertion methods are injected as delegates, making the core logic framework-agnostic.


Sample Code Walkthrough

The _SampleCodes folder contains a complete BirthDay class example:

The Testable Class

// _SampleCodes/Testables/SampleClasses/BirthDay.cs
public class BirthDay : IComparable<BirthDay>
{
    public string Name { get; init; }
    public DateOnly DateOfBirth { get; init; }

    public BirthDay(string name, DateOnly dateOfBirth) { ... }
    public int CompareTo(BirthDay? other) => ...;
}

The Data Source (Framework-Agnostic)

// _SampleCodes/DataSources/TestDataSources/BirthDayDataSource.cs
public class BirthDayDataSource
{
    // TestData<DateOnly> β€” general constructor scenarios
    public IEnumerable<TestData<DateOnly>> GetBirthDayConstructorValidArgs()
    {
        const string result = "creates BirthDay instance";
        
        string definition = "Valid name and dateOfBirth is equal with the current day";
        DateOnly dateOfBirth = Today;
        yield return createTestData();  // ← Local method pattern

        #region Local Methods
        TestData<DateOnly> createTestData()
        => CreateTestData(definition, result, dateOfBirth);
        #endregion
    }

    // TestDataThrows<ArgumentException, string> β€” exception scenarios
    public IEnumerable<TestDataThrows<ArgumentException, string>> GetBirthDayConstructorInvalidArgs() { ... }

    // TestDataReturns<int, DateOnly, BirthDay> β€” return-value scenarios
    public IEnumerable<TestDataReturns<int, DateOnly, BirthDay>> GetCompareToArgs() { ... }
}

Test Classes (One Data Source β†’ Four Frameworks)

Framework Instance Mode Properties Mode
xUnit v2 _UnitTests/xUnit/ _UnitTests/xUnit/
xUnit v3 _UnitTests/xUnit_v3/ _UnitTests/xUnit_v3/Specific/
MSTest 4 _UnitTests/MSTest/Native/..._Instance.cs _UnitTests/MSTest/Native/..._Properties.cs
NUnit 4 _UnitTests/NUnit/Native/..._Instance.cs _UnitTests/NUnit/Native/..._Properties.cs
# Run the MSTest sample
dotnet test _SampleCodes/_UnitTests/MSTest/

# Run the NUnit sample
dotnet test _SampleCodes/_UnitTests/NUnit/

# Run the xUnit v3 sample
dotnet test _SampleCodes/_UnitTests/xUnit_v3/

Prerequisites

  • .NET 10 SDK (Preview or later)
  • Visual Studio 2022 17.14+ with Text Template Transformation component (for T4 regeneration)
  • One or more test frameworks:
    • xUnit v2 (xunit 2.x)
    • xUnit v3 (xunit.v3 3.2.2+)
    • MSTest 4 (MSTest.TestFramework 4.0.2+)
    • NUnit 4 (NUnit 4.4.0+)

Contributing

Contributions are welcome! Here's how to get started:

1. Fork and Branch

git checkout -b feature/my-improvement

2. Follow Code Conventions

  • SPDX license headers on all .cs files
  • init-only properties for immutability
  • XML doc comments on public APIs
  • Local methods with #region Local methods for encapsulation
  • Naming: camelCase for local methods, PascalCase for public APIs

3. Regenerate T4 Output (If Applicable)

If you modified any .tt or .ttinclude files:

# In Visual Studio:
# Right-click the .tt files β†’ Run Custom Tool
# Commit the updated .generated.cs files

4. Build and Test

dotnet build
dotnet test

5. Open a Pull Request

Submit against master with a clear description.

Branch Conventions

Branch Purpose
master Stable, production-ready code
Without_tt Pre-T4 baseline (manual generic classes)
T4 T4 template development

Reporting Issues

Use GitHub Issues with:

  • Steps to reproduce
  • Expected vs. actual behavior
  • .NET SDK version and test framework

Repository Statistics

  • Created: January 16, 2026 (46 days ago)
  • Language: C#
  • Size: ~7,223 KB
  • Stars: ⭐ 1
  • Forks: 0
  • Open Issues: 0
  • License: MIT
  • Visibility: Public

View Recent Commits | View All Activity


Why Portamical?

Portamical elevates test data from a framework concern to a domain concern. It treats test cases as immutable, identity-driven value objects, enabling:

  • βœ… Portability: Write once, run on xUnit, MSTest, and NUnit
  • βœ… Strong Typing: Generics up to 9 arguments (T4-generated)
  • βœ… Deduplication: Automatic via identity-based HashSet<INamedCase>
  • βœ… Self-Documentation: Test names read like specifications
  • βœ… Immutability: init-only properties throughout
  • βœ… Zero Boilerplate: Factory pattern + T4 code generation
  • βœ… Unified Assertions: PortamicalAssert with delegate injection

Ideal For

  • Large test suites (500+ parameterized tests)
  • Multi-framework environments
  • Domain-heavy logic with many edge cases
  • Projects needing human-readable test reports
  • Teams needing clarity, consistency, and maintainability

License and project lineage

This project is licensed under the MIT License.

Portamical.Core is the continuation and successor of CsabaDu.DynamicTestData.Core (also MIT-licensed).
CsabaDu.DynamicTestData.Core is considered legacy and is no longer supported; new development happens in Portamical.

What changed compared to CsabaDu.DynamicTestData.Core?

Portamical continues the original ideas, with important corrections and refinements:

  • Data model: moved away from a record-based model (which proved to be a wrong fit) to immutable classes.
  • Identity: improved test case name construction and identity handling:
    • more effective name construction (Span-based)
    • deduplication via a comparer
  • Naming/clarity: several concepts were renamed for readability and long-term maintainability (e.g., PropsCode values and related terms).

Migration guidance (high level)

If you are using CsabaDu.DynamicTestData.Core:

  • Prefer migrating to Portamical.Core for continued support and improvements.
  • Expect mostly mechanical renames, restructured namespaces, plus updates where the API surface changed due to the move from records to immutable classes.

If you want, we can add a dedicated MIGRATION.md with:

  • package replacement mapping
  • namespace/type rename table
  • common before/after snippets


Made by CsabaDu

Portamical: Test data as a domain, not an afterthought.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Portamical.Core:

Package Downloads
Portamical

Shared utilities and base classes for cross‑framework test data solutions in .NET, built on the Portamical.Core data model.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0 116 3/13/2026
1.0.3 81 3/8/2026
1.0.2 80 3/7/2026
1.0.1 134 3/6/2026
1.0.0 81 3/4/2026

Initial releas