Return custom ResultSource from Results property

Is it possible to add void PublishTable(ResultTable table) to the IResultSource interface. I want my custom base step to return another interface to publish Results by hiding the base Results property.

Simplified example:

public abstract class ResultSourceDecorator : IResultSource
{
	readonly IResultSource _resultSource;
	
	public ResultSourceDecorator(IResultSource resultSource)
	{
		_resultSource = resultSource;
	}
}

public interface IMyResultSource
{
	void MyPublishMethodA(args);
    void MyPublishMethodB(args);
}

public class MyResultSource : ResultSourceDecorator, IMyResultSource
{
    // Contains a cache for creation of ResultTables, therefore: 
    // PublishTable(Resultable table) is the best/only option I can use.

	void MyPublishMethodA(args)
	{
		ResultTable table = ... // create table from args
		PublishTable(table)		//  => not defined in IResultSource
	}

	void MyPublishMethodB(args)
	{
		...
	}
}

public abstract class MyBaseTestStep : TestStep
{
	public new IMyResultSource Results => new MyResultSource(base.Results);
	
	...
}

Hi @steve.vandenbussche,

Without understanding 100% what want to do… Could you do this by adding an extension method?

Hi @rolf_madsen

Most of my test steps publish results using the following class:

// simplified version
public class TestResult<T> : ITestResult where T : IConvertible
{
    public string Name { get; set; }
    public T Value { get; set; }
    public string Condition { get; set; }
    public string Verdict { get; set; }
}

Results contains a method: void Publish<T>(T result), which works for a single item and an array of items, but you cannot specify a name for the result table (it’s default the type name). Therefore I want to implement a new method: PublishTable<T>(string name, params T[] results) , and hide the original one. I could use an extension method, maybe I’m making things to complex.

public void PublishTable<T>(string tableName, T[] results) where T : ITestResult
{
    PropertyInfo[] props = typeof(T).GetProperties()
        .Where(x => x.CanRead && typeof(IConvertible).IsAssignableFrom(x.PropertyType)).ToArray();

    ResultColumn[] columns = new ResultColumn[props.Length];

    for (int i = 0; i < props.Length; i++)
    {
        Array columnData = Array.CreateInstance(props[i].PropertyType, results.Length);

        for (int r = 0; r < results.Length; r++)
            columnData.SetValue(props[i].GetValue(results[r]), r);

        string columnName = props[i].GetCustomAttribute<DisplayAttribute>()?.Name ?? props[i].Name;

        columns[i] = new ResultColumn(columnName, columnData);
    }

    PublishTable(new ResultTable(tableName, columns));
}

I think what you say makes sense, but again, it is probably easiest to do this with an extension method, but if you can wait until OpenTAP 9.23, I also encurage you to submit a pull request.

The affected code is here: https://github.com/opentap/opentap/blob/ecf58e3ad44b66abbd6ff0d7254c1c02127a82d1/Engine/ResultProxy.cs#L426C1-L426C9

You’ll notice the code might be a bit more complicated than you’d initially think, but there are some performance considerations to think about.

In your case, I guess you could just copy the code for ToResultTable and then set the name afterwards.

Thanks for your reply.

I missed it :face_with_hand_over_mouth: there is a method Publish<T>(string name, T result) which does what I need. Maybe to much code the last days…

1 Like