Calling super.run_phase from and extended-extended test, but just want base test.run_phase

Hi, I’m hoping to get a better understanding of run_phase overriding with extended classes. There are several ways to solve this problem, but I’m curious about how thing work, or should be done in the following scenario.

  1. I have a base_test “B” that runs some initialization tasks for every test.
  2. I also have an extended base test “EB” that calls super.run_phase and adds several tasks for that EB.
  3. Then I realized I need another test that could use some of EB’s tasks, so I extended EB to create an extended extended test “EEB”

In EEB, I don’t want to run EB’s run phase so I don’t call super.run_phase, but I do want to run the B’s run phase.

Question on understanding: How does the run_phase overriding work with respect to super.run_phase? If I create a run_phase in EEB, but don’t call super.run_phase, I won’t get B’s run_phase to execute. If I do call it, EB’s tasks all get called.

Question about understanding ‘virtual’: If I make run_phase virtual in the parent classes, don’t they get ‘replaced’ with EEB’s run_phase in all the sub-classes with this new run_phase? If virtual, and my EEB run_phase calls super.run_phase, which super is executed?

Thanks for your insights and explanations, I appreciate all your help and advise.

You can access base members from a derived class by calling B::run_phase() instead of super.run_phase().

A declaration overriding a class member never “replaces” the member,–it just hides the base member’s declaration from the sub-class.

A reference to super.member means start searching for the member from the super-class this sub-class was extended from. It keeps searching up the inheritance chain until it the member declaration is found.
A reference to classname::member means start searching from that particular classname and keep searching up the inheritance chain until found.

Thanks Dave, I learned of B::run_phase() concept from one of your other comments years ago and did use it in this case and it worked beautifully to solve the problem but I’m curious about it.

I just haven’t seen it used very much. (I’ll admit that My visibility is only limited to what’s seen on line and at a few ‘sizable’ companies; but it’s a big world out there). This scenario seems like it would be common, so I suspect there are better ways to do things so this isn’t needed.

Is using the B::run_phase() concept commonly used, or are the recommendations on how to architect the tests and extended classes that avoid it and make things easier? What would recommendations be toward structuring a complex testbench that will have tests extending other tests… I know every situation is different, just looking for some general test-architecture guidance; e.g. :

  1. Should the base test to just provide tasks and functions and not actually call them so extended tests are more in control and avoid calling super.run_phase.
  2. Should extended classes that add additional tasks just be placed in an extended_base class and mimic the original base_class strategy that doesn’t call them, just provides them for the extended-extended classes to call?

I’m not sure that the ‘virtual’ concept has much use here in the test run_phase area, if there is any guidance there, I’d be interested in hearing if it’s very helpful and how it would be useful.

Thanks again

I too have not seen it used, but people do ask about needing this functionality a lot. It mentioned by one sentence in the LRM (section 8.23 Class scope resolution operator ::) without any examples. It’s also a hard feature to search for, even if you know what you are looking for.

Another point of confusion might be the fact that people are so used to seeing a call to super.new() as the first line of an extended constructor, its easy to overlook that you have so many other options with overridden methods that are not constructors.

  1. The call doesn’t have to be the first line; it can come at the end or in the middle.
  2. Calling super.new is optional and may be conditional.
  3. You can skip over any any number of inhertance levels as we have just mentioned above.

I’m not sure anyone can make a generic recommendation without more details that would be difficult to present in this forum. I hope other people will offer their opinions.

One last suggestion in a slightly different direction is looking at this paper on the Design Patterns, specifically the Strategy pattern. I think it gives you the most flexibility in organizing the “behaviors” or your test.

Thanks Dave, I appreciate it. I’ll take a look at the paper, and wait to see if anyone has any other thoughts on how to best organize your program’s tests - some practical examples of what people generally put in their base test vs extended tests and strategies for calling super.run_phase()… e.g., do some people put run_phase tasks in the base test to simply enable clocks and resets, and then just include common tasks that other children might want…

Many thanks for always being there to lend a hand,
Brian