Cucumber: Creating a step definition that depends on another step - cucumber

I need to setup a cascading "Given" -- one factory that belongs_to the factory before it ... in plain rspec, I'd create he first factory, then take it's ID and pass it to the next factory.
#widget = Factory(:something)
#otherthing = Factory(:other, :widget_id => #widget.id)
What's the best way to do this in a step definition? My scenario says: "Given a widget AND a thing", but that creates two steps that don't seem to know anything about the other.

You can use the same approach as RSpec. A step can access instance variables set in a different step.

As Andy says - steps within a scenario can share state with each other through instance variables (because each scenario is executed within a new instance of the World object).
In your case I'd write something like:
Given /^a widget$/ do
#the_widget = Factory(:something)
end
Given /^a thing$/ do
raise "Must create a widget first!" if #the_widget.nil? # In case the scenario author forgets the widget-creation step
#the_otherthing = Factory(:other, :widget_id => #widget.id)
end

Related

If instances are really just pointers to objects in Python, what happens when I change the value of a data attribute in a particular instance?

Suppose I define "Class original:" and create a class attribute "one = 4." Then I create an instance of the class "First = original()." My understanding is that First now contains a pointer to original and "First.one" will return "4." However, suppose I create "Second = original()" and then set "Second.one = 5." What exactly happens in memory? Does a new copy of Class original get created with a class attribute of 5?
I've created a Class original with class attribute one. I then created two instances of this class (First and Second) and verified that id(First.one) and id(Second.one) are pointing to the same place. They both return the same address. However, when I created Third=original() and set Third.one = 5 and then check id(Thrid.one) it appears to be pointing somewhere else. Where is it pointing and what happened? When I check original.one it still returns "4" so obviously the original object is not being modified. Thanks.
It appears you are asking about a piece of code similar to this:
class Original:
def __init__(self, n):
self.one = n
first = Original(4)
second = Original(4)
third = Original(5)
print(id(first.one))
# 140570468047360
print(id(second.one))
# 140570468047360
print(id(third.one))
# 140570468047336
Suppose I define "Class original:" and create a class attribute "one = 4." Then I create an instance of the class "First = original()." My understanding is that First now contains a pointer to original
No. The variable references the instance you created, not the class. If it referenced the class, there would be no way for you to get at the instance you just created.
The instance will, somewhere in its object header, of course contain a pointer to its class. Without that pointer, method lookup wouldn't be possible, since you wouldn't be able to find the class from the instance.
and "First.one" will return "4."
Yes. The attribute one of first contains a pointer to the object 4 (which is an instance of the class int).
[Note that technically, some Python implementations will perform an optimization and actually store the object 4 directly in the attribute instead of a pointer to the object. But that is an internal implementation detail.]
However, suppose I create "Second = original()" and then set "Second.one = 5." What exactly happens in memory? Does a new copy of Class original get created with a class attribute of 5?
No. Why would you need a separate copy of the class? The methods are still the same for both instances. In fact, that is precisely the reason why methods in Python take the instance as their first argument! That way, there need only be one method. (This is actually the same in every OO language, except that in most other languages, this argument is "invisible" and only accessible using a special keyword like self in Ruby, Smalltalk, Self, and Newspeak or this in Java, C#, and Scala.)
I've created a Class original with class attribute one. I then created two instances of this class (First and Second) and verified that id(First.one) and id(Second.one) are pointing to the same place. They both return the same address. However, when I created Third=original() and set Third.one = 5 and then check id(Thrid.one) it appears to be pointing somewhere else.
It is not quite clear to me what your question is here. first.one and second.one both point to 4, so they both point to the same ID since they both point to the same object. third.one points to 5, which is obviously a different object from 4, so naturally, it has a different ID.
It is, in fact, one of the requirement of IDs that different objects that exist at the same time must have different IDs.
Where is it pointing and what happened?
Again, it is not quite clear what you are asking.
It is pointing at 5, and nothing happened.
When I check original.one it still returns "4" so obviously the original object is not being modified.
Indeed, it isn't. Why would it be?

How to use UVM factory's set_inst_override_by_name to override sequence item

I have two sequence item class a_packet and its extended class called bad_packet.
By default, a_packet type is used.
Trying to override a_packet instance with bad_packet, I am able to do it successfully by using set_inst_override_by_name in my uvm test,
factory.set_inst_override_by_name("a_packet","bad_packet", "*");
Now my question is: what if I don't want to use "*", how to know the full hierarchical path of the sequence item instance?
I was trying to utilise get_full_name() from inside the sequence item, right after it is received by the driver, to know the exact hierarchical path. It displayed:
uvm_test_top.env.a_agt.a_seqr.a_sequence.a_packet
But when I replaced the * with above path, the overriding is not happening.
factory.set_inst_override_by_name("a_packet","bad_packet","uvm_test_top.env.a_agt.a_seqr.a_sequence.a_packet");
Did I do something wrong?
Where you create your packet, you'll need to to specify the full path to the corresponding call to create(..):
packet = a_packet::type_id::create("packet", , get_full_name());
If you were using the uvm_do macro, you'll have to change to using the explicit sequence API:
packet = a_packet::type_id::create("packet", , get_full_name());
start_item(packet);
// ... randomize ...
finish_item(packet);
Idea is from this DVCon Paper, section IV.A.

Pass variables between step definitions in Cucumber groovy

I am wondering how we can pass variables between two step definitions files.
I found this How to share variables across multiple cucumber step definition files with groovy but their structure is different from mine, because I am not using classes in step definition.
The following is my two step definition files.
Feature File 1
Scenario: Consumer registration
When I try to register with my details with "memberNo" mem no.
Then I should be able to get success response
stepDef1
When(~'^I try to register with my details with "([^"]*)" mem no.$') { String memdNo ->
sMemdNo = memNo + getRanNo()
// more code here
}
Feature File 2
Scenario: Event Generation
When I activate my account
Then I can see the file having "logName" event
stepDef2
Then(~'^I can see the file having "([^"]*)" event$') { String logName ->
eventFile = GetLogtData(logName , sMemdNo )
// more code here
}
So, as per the above I want to get the value of sMemdNo from stepDef1 and use it in stepDef2.
I will recommend that you use the World, to store global variables needed across step definitions.
You can see an example here: cucumber-jvm-groovy-example.
You can combine the World with a Factory and/or dependency injection pattern.
To use variables between steps you can add the variable at the top of the steps file (groovy or java), and the variable used in one step will have the value available for other variable.
Example
Result

Referencing an instance of a given class in sequence diagrams

I have to model a system where an object of the class Person will invoke the static method getBook(...) : Book on the class Book which will return an instance of a particular book.
How do you reference the book instance obtained by the operation?
As of now, I can think of two approaches, neither of which I have ever seen/used, which is why I am looking for the correct approach.
The first approach is to invoke methods directly on the book instance obtained, e.g. if the reference returned by getBook(...) : Book is named matchingBook, I would use matchingBook.doSomething(...), much like having a local variable.
The second way, which I find more in the line of sequence diagrams is to let the book instance returned by the operation appear with its own lifeline, e.g. next to the Book class, and referencing it with an arrow labeled doSomething(...).
However, with the second approach, it is not that obvious that this object is in fact the one returned by the operation.
The second approach is the correct. To show that you are pointing to the returned object (matchingBook), you can add the variable name to the title of the lifeline, like this:
The second approach is the correct one. Anytime you call operations on an object returned by a first operation, you can't do better than a name match between the result of the first call and the lifeline.
Anyway I don't really understand what you expect of the first way: where would you put matchingBook.doSomething(...)? on a arrow pointing which lifeline?

SpecFlow -- Step (Given) with the same regex in different classes not executing independently

I have two classes (class A and B) both marked with [Binding]. Currently I'm using a class per feature. Classes A and B both have a step that looks like this:
[Given(#"an employee (.*) (.*) is a (.*) at (.*)")]
public void GivenAnEmployeeIsAAt(string firstName, string lastName, string role, string businessUnitName)
When I run the scenario for the features defined in class A, and the test runner executes the step indicated above, the matching step in class B gets executed instead.
Are "Steps" global as well? I thought only the "hook" methods are global, i.e. BeforeScenario, AfterScenario. I do not want this behavior for "Given", "Then", and "When". Is there any way to fix this? I tried putting the two classes in different namespaces and this didn't work either.
Also, am I potentially misusing SpecFlow by wanting each "Given" to be independent if I put them in separate classes?
Yes Steps are (per default) global. So you will run into trouble if you define two attributes that have RegExps that matches the same Step. Even if they are in separate classes.
Being in separate classes, or other placement (other assembly even) doesn't have anything to do with how SpecFlow groups it - it's just a big list of Given's, When's and Then's that it try to match the Step against.
But there's a feature called Scoped Steps that solves this problem for you. Check it out here: https://github.com/techtalk/SpecFlow/blob/master/Tests/FeatureTests/ScopedSteps/ScopedSteps.feature
The idea is that you put another attribute (StepScope) on your Step Defintion method and then it will honor that scoping. Like this for example:
[Given(#"I have a step definition that is scoped to tag (?:.*)")]
[StepScope(Tag = "mytag")]
public void GivenIHaveAStepDefinitionThatIsScopedWithMyTag()
{
stepTracker.StepExecuted("Given I have a step definition that is scoped to tag 'mytag'");
}
... or to scope an entire step definition class to a single feature:
[Binding]
[StepScope(Feature = "turning on the light should make it bright")]
public class TurningOnTheLightSteps
{
// ...
}
This step definition is using a StepScope for a tag. You can scope your steps by:
Tag
Scenario title
Feature title
Great question! I hadn't fully understood what that was for until now ;)

Resources