Is there a way to retrieve if a Specflow scenario step starts with And or But instead of the Given/When/Then ? I want to write the steps into a text.
Eg:
Given this is a step
And this is another one
When I do something
Then something happen
But something else dont
Is the And/But stored anywhere that I can retrieve?
Thanks!
It could be, that it this information is available in the StepInfo (https://github.com/techtalk/SpecFlow/blob/master/TechTalk.SpecFlow/StepInfo.cs).
[Binding]
public class Binding
{
private ScenarioContext _scenarioContext;
public Binding(ScenarioContext scenarioContext)
{
_scenarioContext = scenarioContext;
}
[AfterStep()]
public void AfterStepHook()
{
var stepText = _scenarioContext.ScenarioStepContext.StepInfo.Text;
}
}
Code written without compiling/running.
Related
I need to find a way to get an instance of DataProcessingEngine without calling it's constractor.
I am trying to find a way to do so using the registered DataProcessingEngine in composition object (please see the following code). But I could not find a way to do so.
Anyone have a suggestion? Thanks in advance.
public class Composer : IUserComposer
{
public void Compose(Composition composition)
{
composition.Register<IDataProcessingEngine, DataProcessingEngine>(Lifetime.Singleton);
//DataProcessingEngine dataProcessing = compostion.Resolve<IDataProcessingEngine>()??//no resolve function exists in Umbraco.Core.Composing
SaveImagesThread(dataProcessingEngine);
}
public Task SaveImagesThread(IDataProcessingEngine dataProcessingEngine)//TODO - decide async
{
string dataTimerTime = WebConfig.SaveProductsDataTimer;
double time = GetTimeForTimer(dataTimerTime);
if (time > 0)
{
var aTimer = new System.Timers.Timer(time);
aTimer.Elapsed += new ElapsedEventHandler(dataProcessingEngine.SaveImages);
aTimer.Start();
}
return default;
}
}
For all of you who are looking for a way to call a function (that's defined in another class in your code, an Engine or ...) from the composer(where the app starts) and want to avoid calling this function's class' constractor. I've found another way to do so:
public class QueuePollingHandler
{
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
public class SubscribeToQueuePollingHandlerComponentComposer :
ComponentComposer<SubscribeToQueuePollingHandler>
{ }
public class SubscribeToQueuePollingHandler : IComponent
{
private readonly IDataProcessingEngine _dataProcessingEngine;
public SubscribeToQueuePollingHandler(IDataProcessingEngine
dataProcessingEngine)
{
_dataProcessingEngine = dataProcessingEngine;
SaveImagesThread(_dataProcessingEngine);
}
public void SaveImagesThread(IDataProcessingEngine
dataProcessingEngine)
{
....
}
}
And the logic explenation: You create a class (SubscribeToQueuePollingHandlerComponentComposer from the example) and define its base class to be ComponentComposer<Class_that_inherits_IComponent>.
And when you start the application you could see that it gets to the registered class' constractor (SubscribeToQueuePollingHandler constructor).
That's the way that I found to be able to call a function right when the application starts without needing to call its class constractor and actualy use dependency injection.
So I have a few tests where i've reused steps from within steps.
But i'm now having a nightmare on the maintenance front, in that I cant easily navigate between the steps.
Here's an example:
[Given(#"I have an order")]
public void GivenIHaveAnOrder()
{
Given("an open store");
Given("I am an existing customer");
Given("I am on homepage");
When("I search for a component");
When("I add the component to my basket");
}
How do I navigate to one of those internal steps?
If I wanted to navigate to the "When("I search for a component");" step I cant.
If I were on the feature file I could simply right click the step and "go to definition" but I cant do that here. Does anyone have a solution?
I assume that you are calling the steps with the Given/When- functions, because they are in a different binding class. Am I right?
There is a better way of doing it, than using this functions.
Did you had a look at the driver concept and context injection?
Have a look here: http://www.specflow.org/documentation/Context-Injection/
Simply extract your logic of your steps to a driver class and get an instance from it in the different step classes:
class Driver
{
public void AnOpenStore()
{
...
}
}
[Binding]
public class StepClass1
{
private Driver _driver;
public StepClass1(Driver driver)
{
_driver = driver;
}
[Given(#"I have an order")]
public void IHaveAnOrder()
{
_driver.AnOpenStore();
}
}
[Binding]
public class StepClass2
{
private Driver _driver;
public StepClass2(Driver driver)
{
_driver = driver;
}
[Given(#"an open store")]
public void AnOpenStore()
{
_driver.AnOpenStore();
}
}
When you arrange your step implementations like that, the reusing of other steps is much more easier.
I'm trying to establish a way of unit testing my service layer (& repositories) using some dummy data. I've seen examples of this before with Generic Repositories but I'm struggling to get something working whilst using a DatabaseFactory.
When I call the GetPhrase method from repository.Object I just get null back everytime.
I'm using NUnit and Moq. Any pointers on where i'm going wrong would be appreciated, or let me know if i'm better off going down a different road
e.g. Connecting to a local db for tests (SQL CE etc)
Here are the main components of the code:
public class PhraseRepository : RepositoryBase<Phrase>, IPhraseRepository
{
public PhraseRepository(IDatabaseFactory databaseFactory)
: base(databaseFactory)
{
}
public string GetPhrase(string phraseCode)
{
return this.GetMany(p => p.PhraseCode == phraseCode).First().Descript;
}
}
public interface IPhraseRepository : IRepository<Phrase>
{
string GetPhrase(string phraseCode);
}
public class CLPRiskPhraseService : ICLPRiskPhraseService
{
private readonly IPhraseRepository phraseRepository;
public string GetPhrase(string phraseCode)
{
return phraseRepository.GetPhrase(phraseCode);
}
}
[Test]
public void GetPhrase()
{
var phrases = new FakePhraseData().GetPhrases();
phraseRepository.Setup(m => m.GetMany(It.IsAny<Expression<Func<Phrase, bool>>>())).Returns(phrases);
var result = phraseRepository.Object.GetPhrase("H300");
// Assert
NUnit.Framework.Assert.IsNotNull(phraseRepository.Object);
NUnit.Framework.Assert.AreEqual("Description0", result);
}
Invoking phraseRepository.Object.GetPhrase("H300") in your test will always return null unless you set it up to return something different.
I think you're mistakenly thinking that this call to GetPhrase will invoke GetMany like the concrete PhraseRepository does, but you need to remember that it's just a mock of the interface IPhraseRepository. A method on a mocked object will always return the default value of the return type (in this case string) unless you use Setup to change the behavior of that method.
I found grails criteria and want to customize sorting options.
E.g. I have domain Book and I want to make some criteria:
Book.createCriteria().list {
//some code like ilike('name', 'book')
...
order(params.sort, params.order)
}
I want to make specific sorting rule, e.g. by name.trim().
How can I do this?
Based on a solution provided here, by extending the hirbernate Order class, you can customize it to accept functions and use it with createCriteria.
I wont be surprised, if there is a nicer and easier approach since this source is pretty old and also Grails is cooler than this :D
First you need a class extending Hibernate Order:
Originally by:spostelnicu
public class OrderBySqlFormula extends Order {
private String sqlFormula;
protected OrderBySqlFormula(String sqlFormula) {
super(sqlFormula, true);
this.sqlFormula = sqlFormula;
}
public String toString() {
return sqlFormula;
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return sqlFormula;
}
public static Order sqlFormula(String sqlFormula) {
return new OrderBySqlFormula(sqlFormula);
}
}
Then you can pass instance of this class to your createCriteria:
def ls = Domain.createCriteria().list {
order OrderBySqlFormula.sqlFormula("TRIM(name)")
}
Note1: You can pass any formula to sqlFormula as long as the underlying database accepts it.
Note2: Using such approach might cause migration challenges.
Hope it helps
We're trying to implement global hooks on our specflow tests and are not entirely sure how [BeforeScenario] and [AfterScenario] attributed methods work.
The way I've seen it done, those attributes are always defined in a class containing specific steps used in a few scenarios.
Can they go somewhere so they apply to all scenarios? Or does attributing the methods with [BeforeScenario] and [AfterScenario] cause them to be run for all scenarios, regardless of where they're actually placed?
Hmm... From what I knew and according to the documentation these hooks are always global, i.e. from http://www.specflow.org/documentation/hooks/
Hooks
The hooks (event bindings) can be used to perform additional automation logic on specific events, like before the execution of a scenario.
The hooks are global but can be restricted to run only for features or scenarios with a specific tag (see below). The execution order of hooks for the same event is undefined.
In fact by producing a small demo project with the following
[Binding]
public class Unrelated
{
[BeforeScenario]
public void WillBeCalledIfGlobal()
{
Console.WriteLine("I'm global");
}
}
[Binding]
public class JustTheTest
{
[Given("nothing")]
public void GivenNothing()
{
// Don't do anything
}
}
Then the test specification of
As a developer
In order to understand how BeforeSpecifcation works
I want to know what the following does
Scenario: See if BeforeSpecifcation hook gets called
Given nothing
The get the output
I'm global
Given nothing
-> done: JustTheTest.GivenNothing() (0.0s)
So it really does look as if the documentation is correct, and you should use tagging to control if the BeforeScenario \ AfterScenario are run before or after your scenario.
There is also a good example of how tagging works here -> Feature-scoped step definitions with SpecFlow?
Yes, you can create global BeforeScenario and AfterScenario methods, but in practice I find that this is not desirable, as usually the same before and after steps do not apply to all steps in a test project.
Instead I create a base class for my step definitions, which would have the BeforeScenario and AfterScenarios methods I'd like applied to all of my scenarios e.g.
public class BaseStepDefinitions
{
[BeforeScenario]
public void BeforeScenario()
{
// BeforeScenario code
}
[AfterScenario]
public void AfterScenario()
{
// AfterScenario code
}
}
Note that I have not used the Binding attribute on this class. If you do include it then the BeforeScenario and AfterScenario steps would be global.
I then derive my step definion classes from this base step definition class, so that they will have the Before and After scenario methods e.g.
[Binding]
public class SpecFlowFeature1Steps : BaseStepDefinitions
{
[Given(#"I have entered (.*) into the calculator")]
public void GivenIHaveEnteredIntoTheCalculator(int inputValue)
{
ScenarioContext.Current.Pending();
}
[When(#"I press add")]
public void WhenIPressAdd()
{
ScenarioContext.Current.Pending();
}
[Then(#"the result should be (.*) on the screen")]
public void ThenTheResultShouldBeOnTheScreen(int expectedResult)
{
ScenarioContext.Current.Pending();
}
}
Whilst this approach is not global, by making all StepDefinitions derive from a BaseStepDefinition class we achieve the same outcome.
It also gives more control i.e. if you don't want the BeforeScenario or AfterScenario binding then don't derive from the base steps.
Sorry this doesn't work. As soon as you start using multiple Binding classes you end up with multiple calls. For example if I extend the example above to split the bindings into three classes,
[Binding]
public class SpecFlowFeature1Steps : BaseStepDefinitions
{
[Given(#"I have entered (.*) into the calculator")]
public void GivenIHaveEnteredIntoTheCalculator(int inputValue)
{
//ScenarioContext.Current.Pending();
}
}
[Binding]
public class SpecFlowFeature2Steps : BaseStepDefinitions
{
[When(#"I press add")]
public void WhenIPressAdd()
{
//ScenarioContext.Current.Pending();
}
}
[Binding]
public class SpecFlowFeature3Steps : BaseStepDefinitions
{
[Then(#"the result should be (.*) on the screen")]
public void ThenTheResultShouldBeOnTheScreen(int expectedResult)
{
//ScenarioContext.Current.Pending();
}
}
public class BaseStepDefinitions
{
[BeforeScenario]
public void BeforeScenario()
{
// BeforeScenario code
Console.WriteLine("Before. [Called from "+ this.GetType().Name+"]");
}
[AfterScenario]
public void AfterScenario()
{
// AfterScenario code
Console.WriteLine("After. [Called from " + this.GetType().Name + "]");
}
}
Then when I run it, the output is
Before. [Called from SpecFlowFeature1Steps]
Before. [Called from SpecFlowFeature2Steps]
Before. [Called from SpecFlowFeature3Steps]
Given I have entered 50 into the calculator
-> done: SpecFlowFeature1Steps.GivenIHaveEnteredIntoTheCalculator(50) (0.0s)
And I have entered 70 into the calculator
-> done: SpecFlowFeature1Steps.GivenIHaveEnteredIntoTheCalculator(70) (0.0s)
When I press add
-> done: SpecFlowFeature2Steps.WhenIPressAdd() (0.0s)
Then the result should be 120 on the screen
-> done: SpecFlowFeature3Steps.ThenTheResultShouldBeOnTheScreen(120) (0.0s)
After. [Called from SpecFlowFeature1Steps]
After. [Called from SpecFlowFeature2Steps]
After. [Called from SpecFlowFeature3Steps]
What you can do, in order to control the 'BeforeScenario' and 'AfterScenario' is use tags. This gives you the control of which Scenario's should run which before and after block. Your scenario would look like this:
#GoogleChrome
Scenario: Clicking on a button
Given the user is on some page
When the user clicks a button
Then something should happen
Here you could let the 'BeforeScenario' start a browser session in Google Chrome for you, and implement similar tags for different browsers. Your 'BeforeScenario' would look like this:
[Binding]
class Browser
{
[BeforeScenario("GoogleChrome")]
public static void BeforeChromeScenario()
{
// Start Browser session and do stuff
}
[AfterScenario("GoogleChrome")]
public static void AfterChromeScenario()
{
// Close the scenario properly
}
I think using tags is a nice way of keeping your scenario's clean and give you the extra functionality to let you control what each scenario should do.