<TestPlanDir> stays TBD in file path macro string

I have a test step with one of the parameters being a file path. I’d like this path to be relative to the test plan directory, so my parameter is of MacroString type and I’m using <TestPlanDir> as part of the path.

In my step I use Expand() method to render the path but I see that <TestPlanDir> expands to TBD even though my test plan is saved to disk.

I checked the implementation of Test Plan Reference test step and found out that <TestPlanDir> expansion is handled very explicitly there. Is it something I have to do in my test step as well? I was under the impression <TestPlanDir> is supported by macro strings out of the box or is it only applicable to result listeners?

1 Like

Looking at the unit tests we have, it seems that TestPlanDir should work for all test steps (as long as they are in a saved test plan). I think you need to set MacroString.Context to ‘this’ inside the test step for TestPlanDir to work. Otherwise the MacroString class cannot resolve the test plan to get access to that macro value.

For example you can initialize the MacroString like this:

PathToThing = new MacroString(this) {Text = "<TestPlanDir>/thing"};
1 Like

Thanks, that worked. I thought it’s enough to pass planRun when expanding but apparently it’s not the case.

1 Like

Actually, that should also work. At least, this test that I made passes.

        public void MacroStringTestPlanDirFromArgument()
            var filename = Path.Combine(Path.GetTempPath(), "OpenTapTest", Guid.NewGuid() + ".TapPlan");
            var plan = new TestPlan();
            var planRun = plan.Execute();

            var expandedString = new MacroString() { Text = "<TestPlanDir>\\test.x" }.Expand(planRun);
            Assert.AreEqual(Path.Combine(Path.GetTempPath(), "OpenTapTest",  "test.x"), expandedString);


When do you call ‘expand’ to be precise?

1 Like

Actually, adding this doesn’t really help. When I create a step it’s all fine, but when I reopen test plan it’s again TBD. I tried expanding in different places but without luck, what is the right place to do that?

@tatiana.boye, that does not sound so good…

Maybe that is why this is done in the TestPlanReference code:

public MacroString Filepath
            get => filepath; 
            set {

                filepath = value;
                filepath.Context = this;
               // ...

can you try that and see if it fixes your issue?

Thanks, this seems to help. I haven’t been able to reproduce the issue so far.
Would be nice to have it documented or, even better, eliminate the need of it…

1 Like

Ok, great.

I agree… I don’t think it is the intention that you should have to set Context all the time.

Added issue here: Set MacroString.Context on deserialization · Issue #931 · opentap/opentap · GitHub


@tatiana.boye, I am trying to reproduce the issue you had, but actually this seems not to be possible for me.

Were your MacroString a property on a step or how did you use it?

1 Like

Hello everyone,

I can still reproduce this.

I have updated to the latest 9.20 RC but there is no change.

If I open an already existing TestCase, old steps are fine.
However if I add a new step (that did not exists before I open) TBD stays as TBD

Cannot figure out why


@connospp Thanks for bringing this thread back to life!

@rolf_madsen Sorry, I somehow overlooked your message. I used it as a property of the step indeed.

Ok, this makes sense. It is because you only set Context in the setter, but in your case, that never gets called (Only when loaded later). To fix it, initialize the MacroString object in the constructor:

   public MacroString TheMacroString{get;set;}
   public MyTestStep()
        // Initialize it in the constructor to set Context.
        TheMacroString = new MacroString {Text = "", Context = this};

@tatiana.boye, could this be your issue as well?

1 Like

Yes, also setting context in get{ } fixes it

Thanks @rolf_madsen

Currently I’m not setting the context in the constructor, only in setter. Although it seems to work in my specific case, I think I need to add it to the constructor, too.

@rolf_madsen Just to confirm, you haven’t been able to reproduce the issue when you don’t set the context whatsoever?

That’s right, I have not been able to reproduce this issue.

If you can create and share a simple project which reproduces the issue I can probably fix it, but currently I have no idea.