Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix identification properties and parameter formatting #395

Merged
merged 21 commits into from
Oct 12, 2023

Conversation

delatrie
Copy link
Contributor

@delatrie delatrie commented Oct 12, 2023

Context

There are issues with the current algorithms behind identification properties (uuid, fullName, historyId) that may lead to unexpected behavior. This includes:

  • Different tests might be considered as retries
  • Test results of the same parametrized test case might be considered as different test cases.

More details in this issue: #387.

Additionally, all integrations don't set testCaseId (see #373).

Parameter serialization

Parameter values are one of the inputs to the decision on whether two test results are retries of a single test or two different tests of a parametrized test case.

Current formatting implementation though often formats different values into undistinguishable strings. For example, many collections are serialized just as type names. The same goes for user-defined types that don't override ToString.

Additionally, custom type formatters although are present in the code, actually aren't used in the preview branch (see #377).

Implementation details

A new set of API was added for integrations to calculate identification properties:

public static string Allure.Net.Commons.Functions.IdFunctions.CreateUUID();
public static string Allure.Net.Commons.Functions.IdFunctions.CreateFullName(System.Type targetClass);
public static string Allure.Net.Commons.Functions.IdFunctions.CreateFullName(System.Reflection.MethodBase method);
public static string Allure.Net.Commons.Functions.IdFunctions.CreateTestCaseId(string fullName);
public static string Allure.Net.Commons.Functions.IdFunctions.CreateHistoryId(string fullName, System.Collections.Generic.IEnumerable<Parameter> parameters);

UUID

A UUID is created with System.Guid.NewGuid().

Class-based fullName

This fullName can be used as a name of class-level test containers. It has the following format:

<assembly>:<namespace>.<class-name>`<generic-param-count>[<generic-parameters>]
  • assembly - the name of the assembly of the class
  • namespace - the namespace of the class (optional; excluded with the following dot if the namespace is empty)
  • class-name - the name of the class
  • generic-param-count - the number of generic parameters of the class
  • generic-parameters - the list of the generic parameters or arguments of the class

The generic part starting from the backtick is excluded if the class doesn't have generic parameters.

Method-based fullName

This fullName can be used as a name of a test result that is based on a test method. It has the following format:

<class-fullName>.<method-name>[<generic-parameters>](<parameters>)
  • class-fullName - the fullName of the declaring class calculated using the rules above
  • generic-parameters - the list of the generic parameter of the method
  • parameters - the comma-separated list of the parameters of the method. Each parameter is represented as fullName of its type (assembly name is not included for system types and generic parameter types).

testCaseId

The value of testCaseId is calculated based on fullName. It's required that the fullName doesn't depend on test parameters (fullNames calculated using the functions above satisfy this rule).

MD5 hashing algorithm is used to convert a fullName to the corresponding testCaseId.

historyId

This value depends on the fullName and the list of the parameters of the test. Parameters are sorted by their names. The names are then discarded (only values are used in the calculation).

The actual value is calculated as the MD5 hex digest of the following JSON object:

{
    "fullName": "<fullName>",
    "parameters": "<ordered-parameter-values>"
}

useLegacyIds configuration property

A new configuration property was added to allureConfig.json to use old algorithms for identification properties of test results. This switch can be used as a temporary solution to preserve connection to existing test cases until allure ids are assigned to tests.

Parameters serialization

A new set of API was added for integrations to format step and test parameters:

publis static string Allure.Net.Commons.Functions.FormatFunctions.Format(object? value);
publis static string Allure.Net.Commons.Functions.FormatFunctions.Format(object? value, System.Collections.Generic.IReadOnlyDictionary<System.Type, Allure.Net.Commons.ITypeFormatter> formatters);
public void Allure.Net.Commons.TestResult.AddParameter(string name, object value, System.Collections.Generic.IReadOnlyDictionary<System.Type, Allure.Net.Commons.ITypeFormatter> formatters);

They format the value using the following algorithm:

  1. If the type of the value matches a formatter in the formatters dictionary, the matched formatter is used to convert the value to a string.
  2. Otherwise, the value is JSON-serialized.

These functions are used in the following contexts in allure-nunit, allure-xunit and allure-specflow:

  1. To format a test parameter value when adding the parameter to the test result.
  2. To format a step parameter when interpolating it into the step's title.
  3. To format a step parameter value when adding the parameter to the step result.

In all contexts all type formatters added to the lifecycle via AllureLifecycle.AddTypeFormatter are used.

Other changes

JSON schemas for configuration and testplan

This PR adds schemas for allureConfig.json and testplan.json files. A schema can be added to the document as follows:

{
    "$schema": "https://raw.githubusercontent.com/allure-framework/allure-csharp/<version>/<package>/Schemas/<schema-name>"
}

For example, to apply the schema v2.10 to Allure.NUnit's configuration file, the following URL can be used:

{
    "$schema": "https://raw.githubusercontent.com/allure-framework/allure-csharp/2.10.0/Allure.NUnit/Schemas/allureConfig.schema.json"
}

The release.yml workflow definition file has been updated to put version tags to schema paths.

Language and framework labels

The following methods were added to the public API for integration authors:

public static Allure.Net.Commons.Label Allure.Net.Commons.Label.Language();
public static Allure.Net.Commons.Label Allure.Net.Commons.Label.Framework(string value);

Allure-nunit, allure-xunit and allure-specflow now define these labels for all test results they create.

Checklist

Fixes #345
Implements #373
Fixes #377
Implements #387

UseLegacyIds option is honored.

Additionally:
  - fix uuid for containers
  - fix missing historyId for ignored tests. Same id rules apply as for non-ignored tests (fixes #345)
  - add NUnit 3 framework label to test results
  - remove suites from AllureDisplayIgnored (now suites can be applied directly)
  - fix parameter names for parametrized test methods
Now step title interpolation and step parameter value conversion uses the same
algorithm as test parameter conversions.

Fixes #377
Legacy identifiers switch is honored.

Additionally:
  - Add framework and language labels to allure-xunit test results
  - Fix test parameters formatting. Custom type formatters are also used now
@delatrie delatrie added the task:improvement Change that improves some user experience but can't be considered a new feature label Oct 12, 2023
@delatrie delatrie requested a review from neparij October 12, 2023 07:37
Allure.Net.Commons/Steps/AllureStepAspect.cs Outdated Show resolved Hide resolved
Allure.NUnit/Core/AllureNUnitHelper.cs Outdated Show resolved Hide resolved
Allure.XUnit/AllureXunitHelper.cs Outdated Show resolved Hide resolved
Allure.SpecFlowPlugin/PluginHelper.cs Outdated Show resolved Hide resolved
@neparij neparij added type:improvement and removed task:improvement Change that improves some user experience but can't be considered a new feature labels Oct 12, 2023
@delatrie delatrie requested a review from neparij October 12, 2023 10:42
@neparij neparij merged commit 72890a3 into preview Oct 12, 2023
2 checks passed
@delatrie delatrie deleted the identifiers-fix branch October 13, 2023 07:56
neparij added a commit that referenced this pull request Oct 16, 2023
* Adds AllureBefore and AllureAfter to Allure.NUnit package

* NUnit: Ability to change testresult on fixture executions

* Preserve testResult.start time if it exists in update container

* SpecFlowNunit: add custom labels

* Fix missing output attachments in NUnit adapter

* Added step logging for NUnit (closes #312)

* Fixed NullPointerException if NUnit StepLogger was null (#315)

* embed untracked sources

* build process update

* NUnit Fix async behaviour in [AllureStep] aspect + Allow '{obj.prop}' placeholders in [AllureStep] step name (#329)

Co-authored-by: Кабанов Константин Юрьевич <[email protected]>

* Package assets fix

* NUnit - Add an ability to save OneTimeSetUp step results (#333)

* Handle case when underlying step returns Task<T> masked as non-generic Task (#343)

* Unify xunit and nunit step acpects

* Replace allure-xunit's custom attributes with runner reporter (fixes #344) (#366)

* Add support for native xunit attributes

* Fix AllureXunitTheoryAttribute base class

* Fix missing theories

* Fix missing parameters and fixture duplication for some tests

* Add support for static test functions

* Update xunit examples. Obsolete allure-xunit attributes

* Update message sink to match new steps implementation

* Remove irrelevant log method from runner

* Bump harmony to 2.3-prerelease.2. Warn if no args reported

Change Lib.Harmony dependency to 2.3-prerelease.2 for .net 7 support.
Add warning if the patch via harmony didn't work for theory args and
args aren't reported on the testcase level.

* Fix reference to lib.harmony to be listed by dotnet

* Factor out allure-related code. Tidying up obsolescence

  - Allure-xunit's code that creates, updates, starts, stops and writes
    allure objects is factored out from AllureMessageSink to
    AllureXunitHelper .
  - Removal of AllureXunitHelper's public methods was reverted. The
    methods are marked as obsolete.
  - Add missing await to an allure-xunit example to suppress the
    compilation warning.
  - Mark obsoleted allure-xunit attributes as non-browsable to prevent
    them from appearing in IDE's suggestions.

* Add deprecation info and known issues to allure-xunit README

* Fix issue links in allure-xunit readme

* Fix obsolescence message for AllureXunitHelper's public methods

* New context-based state management model for allure-csharp (#371)

* Add AllureContext lass to isolate allure state from threads and async tasks

* Add concurrency tests. Reformulate context in terms of active/inactive

* Add tests on the context capturing by child threads/tasks

* Modify lifecycle/storage to use new context model. Add context get/set API

* Make CoreStepsHelper use AllureLifecycle's context

* Make lifecycle thread safe. Fix multithreading issues in lifecycle tests

* Several improvements on context. Allure-xunit migration

- Add bool props to test context to context's public API
- Fix context string conversion
- Migrate allure-xunit's code to the new context implementation

* Bump C# language version to 11 for all projects

* Enable null checks in some classes of allure-xunit

* Make lifecycle methods with explicit uuids obsoleted

* Minor changes in context and lifecycle

  - Improve error messages and doc comments
  - Add DebuggerDisplay for context
  - Uuid in string representation of context if names are empty
  - Old storage uuid-based methods obsoleted
  - Make RunInContext return modified context
  - Replace unsupported container nesting with test nested
    into each container in chain
  - Container and test starting now add objects into storage by
    uuids (transition period)

* Rewrite Allure.NUnit to support the new context scheme

* Fix Allure.XUnit usage of RunInContext

* Rewrite Allure.SpecFlowPlugin to support new context scheme

Additionally:
  - Change broken status to failed for some scenario and step conditions
  - Add extra test case instead of changing state of existing one in case
    after feature failed
  - Enable nullable check project-wide

* Separate context from storage

  - AllureContext moved to Allure.Net.Commons namespace
  - Context and storage are separated; Storage will be removed later
  - File scope namespaces for lifecycle and context

* Fix obsolete messages. Add file scoped namespaces

* Revert obsoleted StopFixtureSuppressTestCase to be intact

* Add new info to commons README

* Fix invalid test start. Remove rudimentary test start check

* Remove dotnet SDK 3.1 installation from build pipeline

* Change .NET SDK version to 7.0 in build pipeline

* Github pipelines fix

  - bump actions/checkout to 3.5.3
  - bump actions/setup-dotnet to 3.2.0
  - add dotnet 3.1 and 6.0 SDKs back to build and test
  - Change --no-restore to --no-build in dotnet test step

* Rename a placeholder scenario

* Implement requested changes for PR #371

  - Add allure directory clean before all tests in Allure.NUnit.Examples
  - NUnit.Allure.Core.AllureExtensions.AddScreenDiff is back
    and marked as obsolete (it just directly calls
    AllureLifecycle.AddScreenDiff now).
  - Intendation in Allure.SpecFlowPlugin.csproj fixed.

* NUnit: Fix inconsistent one-time fixtures behavior (fixes #286, #374 and #375) (#380)

* Fix inconsistent one-time fixtures behavior (fixes #374)

* Fix crash when running test from empty namespace (fixes #375)

* Fix indentation for AllureAsyncOneTimeSetUoTests.cs

* Allure-xunit: support for the second reporter and xunit 2.5.0. Updated packaging and AspectInjector (fixes 368) (#382)

* xunit: change sink base, remove redundant err logging

* Add ability to compose xunit runner reporters (implements #368)

* Extract allure-xunit runner reporter into separate project

* Factor out common props. Bump and tune injector

* Reflect new project structure in solution

* Enable fully deterministic build in CI

* Add startup message to Allure.XUnit

* Fix second reporter property name in config for Allure.XUnit's example

* Rewrite how to run section and fix allure-xunit's README

* Fix comment in Directory.Build.props

* Revert AspectInjector build optimization

* Add link to allureConfig.json issue

* Fix release workflow to apply version via .props

* Change net.commons description

It's quite different from allure-java-commons now.

* Improve readability of ResolveExplicitReporter

* Fix typo in allure-xunit README

* release 2.10.0-preview.1

* set next development version 2.11

* Selective run support: commons, nunit, xunit (#390)

* Implement selective run commons

* Change GetAllureId to take an enumeration

* Implement selective run for allure-nunit

* Add a shorthand for testplan's IsMatch

* Implement selective run for allure-xunit

* Move TestPlan property to commons. Rename selection check method

* Allure-specflow: selective run support (#392)

* Fix regression: non-working lambda-steps and lambda-fixtures API (#393)

* allure-xunit: provide default config when allureConfig.json is missing

Fixes #381

* Fix async step/fixture wrapper functions

  - make async Step, Before and After obey .NET's ExecutionContext capturing rules
  - refactor CoreStepsHelper to be more testable
  - write tests for CoreStepsHelper's Step, Before and After

More tests are needed to fully cover CoreStepsHelper.

Fixes #383
Fixed #388

* Add async suffix to private step methods

This helps to make distinction more clear to a reader.

* Fix identification properties and parameter formatting (#395)

* Bump NUnit for test and example projects

* Add json schemas for allureConfig and testplan

* Fix schema for allure-xunit and allure-specflow config

* Add legacy naming switch to config

* Update schema links to current branch

* Add schema links update task to release workflow

* Implement UUID and method-based fullName algorithms

* Common fns to calculate testCaseId, historyId and parameter value

* Add docstrings to new id-related functions

* Add function to create fullName from class

* Fix allureConfig item type for allure-nunit examples

* Add missing setter for UseLegacyIds config property

* Add framework label factory

* Fix uuid, fullName, historyId, testCaseId for allure-nunit

UseLegacyIds option is honored.

Additionally:
  - fix uuid for containers
  - fix missing historyId for ignored tests. Same id rules apply as for non-ignored tests (fixes #345)
  - add NUnit 3 framework label to test results
  - remove suites from AllureDisplayIgnored (now suites can be applied directly)
  - fix parameter names for parametrized test methods

* Apply custom formatters to step title and parameters

Now step title interpolation and step parameter value conversion uses the same
algorithm as test parameter conversions.

Fixes #377

* Add language label to commons and NUnit

* Fix uuid, fullName, historyId, testCaseId for allure-xunit

Legacy identifiers switch is honored.

Additionally:
  - Add framework and language labels to allure-xunit test results
  - Fix test parameters formatting. Custom type formatters are also used now

* Add no-formatters step helper overloads back to public API

* Revert autoedit this removal from StepFunctionTests.cs

* Fix uuid, fullName, historyId, testCaseId for allure-specflow

Legacy ids switch is honored.

Implements #387

* Implement requested changes

* Lower the required AspectInjector version for users back to 2.8.1 (workaround for #391) (#396)

* Add workaround for #391

* Comment AspectInjector workaround step in publish.yml

* Add Rosetta warning in package READMEs. Fix allure-nunit readme

* Update allure-xunit and allure-specflow README (#397)

---------

Co-authored-by: qameta-ci <[email protected]>
Co-authored-by: Andrey Gurenkov <[email protected]>
Co-authored-by: Constantine <[email protected]>
Co-authored-by: Кабанов Константин Юрьевич <[email protected]>
Co-authored-by: Alexander Kulakov <[email protected]>
Co-authored-by: Dmitry Pavlushin <[email protected]>
Co-authored-by: Maxim <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment