How beforeScenario and afterScenario works in JBehave - jbehave

Can someone show examples of how beforeScenario and afterScenario works in JBehave?
I created a class with two methods gearUp with #BeforeScenario and tearDown with #AfterScenario annotations.
But these methods are never invoked in JBehave.
What extra configurations are needed. Any code examples will help us.
Whereas this simple and neat in Cucumber.
Following is my story file with single step(src/test/resources/storeis):
Scenario: SampleTest
Given I am test
Following is my Steps file
public class jbehavetc {
#Given("I am test")
public void startOnUrl(String url) {
System.out.println("I am actual test");
}
}
Following is my Hooks file which contains BeforeScenario and AfterScenario methods
public class Hooks {
#BeforeScenario
public void startSystem() throws Exception {
System.out.println("I am before scenario");
}
#AfterScenario
public void stopSystem() throws Exception {
System.out.println("I am after scenario");
}
}
To run the above story i created a runner file and wanted to run as JUnit Test(Correct me this is not the right approach)
public class JBehaveRunner extends JUnitStory{
#Override
public Configuration configuration() {
return new MostUsefulConfiguration()
.useStoryLoader(
new LoadFromClasspath(getClass().getClassLoader()))
.useStoryReporterBuilder(
new StoryReporterBuilder()
.withDefaultFormats()
.withFormats(Format.HTML));
}
#Override
public InjectableStepsFactory stepsFactory() {
return new InstanceStepsFactory(configuration(), new jbehavetc(),
new Hooks());
}
public List<String> storyPaths() {
return new StoryFinder().findPaths(
CodeLocations.codeLocationFromClass(this.getClass()),
Arrays.asList("**/*.story"),
Arrays.asList(""));
}
#Test
public void run() throws Throwable {
super.run();
}
}
When i run above runner as JUnit test, nothing is getting executed. How can i run above story? I want Before and After Scenario methods needs to be invoked when i run this runner or story file.

You should treat class with #BeforeScenario/#AfterScenario as classes with step implementations: you should register them in your steps factory.
BeforeAndAfterSteps.java
public class BeforeAndAfterSteps {
#BeforeScenario
public void beforeScenario() throws Exception {
// setup
}
#AfterScenario
public void afterScenario() throws Exception {
// teardown
}
}
Example of steps factory configuration
new InstanceStepsFactory(configuration, new BeforeAndAfterSteps())
Official JBehave examples:
Example of the class containing various before/after implementations: BeforeAfterSteps
Examples of this class references and usages:
CoreEmbedder
CoreStory
CoreStories

Following runner file started working for me:
public class JBehaveRunner extends JUnitStories {
#Override
public Configuration configuration() {
return new MostUsefulConfiguration()
.useStoryLoader(
new LoadFromClasspath(getClass().getClassLoader()))
.useStoryReporterBuilder(
new StoryReporterBuilder()
.withDefaultFormats()
.withFormats(Format.HTML));
}
#Override
public InjectableStepsFactory stepsFactory() {
return new InstanceStepsFactory(configuration(), new HomePageSteps(),
new BaseEngine());
}
#Test
public void run() throws Throwable {
super.run();
}
#Override
public List<String> storyPaths() {
return new StoryFinder().findPaths(
CodeLocations.codeLocationFromClass(this.getClass()),
Arrays.asList("**/*.story"),
Arrays.asList(""));
}
}

Related

How to add a hook to the Vertx Launcher

I would like to collect metrics with Vert.x Micrometer Metrics, so I need to set proper options to VertxOptions. I run Vertx with Launcher and there is a hook beforeDeployingVerticle but when I override it it's not called.
I overriden Launcher class and beforeDeployingVerticle method but this method is never executed.
public class LauncherTest {
public static class SimpleVerticle extends AbstractVerticle {
#Override
public void start(Future<Void> startFuture) throws Exception {
System.out.println("verticle started");
}
}
public static class LauncherWithHook extends Launcher {
#Override
public void beforeDeployingVerticle(DeploymentOptions deploymentOptions) {
System.out.println("before deploying");
}
}
public static void main(String[] args) {
new LauncherWithHook().execute("run", SimpleVerticle.class.getName());
}
}
In a result I receive just verticle started, but I expect also to have before deploying there. Should I add this hook somehow different?
change your main method like this:
public static void main(String[] args) {
String[] argz = {"run", "your.namepace.LauncherTest$SimpleVerticle"};
LauncherWithHook launcher = new LauncherWithHook();
launcher.dispatch(argz);
}

How to pass value from rest service to camel route?

I have exposed as service as below
restConfiguration().component("servlet").bindingMode(RestBindingMode.json);
rest("/batchFile").consumes("application/json").post("/routeStart").type(BatchFileRouteConfig.class).to("startRouteProcessor");
Based upon the request from rest service,i would start camel route in processor as below
#Component("startRouteProcessor")
public class StartRouteProcessor implements Processor {
public void process(Exchange exchange) throws Exception {
BatchFileRouteConfig config = exchange.getIn().getBody(BatchFileRouteConfig.class);
String routeId = config.getRouteId();
String sourceLocation = config.getSourceLocation();
exchange.getContext().startRoute(routeId);
}
}
I need to pass the sourceLocation from above bean to below route
#Component
public class FileReaderRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
from("file:sourceLocation")
.log("File Reader Route route started");
}
}
Above is sample code..request you to help me in passing the sourcelocation from StartRouteProcessor to FileReaderRoute
This is not possible, since in your example is FileReaderRoute already started at the time of calling batchFile endpoint.
You can do it in slightly different way.
Extract your FileReaderRoute to direct. Something like:
#Component
public class FileReaderRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
from("direct:fileReaderCommon")
.log("File Reader Route route started");
}
}
And then you can create new route at runtime:
#Component("startRouteProcessor")
public class StartRouteProcessor implements Processor {
public void process(Exchange exchange) throws Exception {
BatchFileRouteConfig config = exchange.getIn().getBody(BatchFileRouteConfig.class);
exchange.getContext().addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
from("file:"+config.getSourceLocation())
.routeId(config.getRouteId())
.to("direct:fileReaderCommon");
}
});
}
}
Do not forget to take sufficient sanitizing of input, since you are allowing user to create file consumer based on user input. In your approach, there is a high risk of path traversal attack.

Spring Batch: File not being read

I am trying to create an application that uses the spring-batch-excel extension to be able to read Excel files uploaded through a web interface by it's users in order to parse the Excel file for addresses.
When the code runs, there is no error, but all I get is the following in my log. Even though I have log/syso throughout my Processor and Writer (these are never being called, and all I can imagine is it's not properly reading the file, and returning no data to process/write). And yes, the file has data, several thousand records in fact.
Job: [FlowJob: [name=excelFileJob]] launched with the following parameters: [{file=Book1.xlsx}]
Executing step: [excelFileStep]
Job: [FlowJob: [name=excelFileJob]] completed with the following parameters: [{file=Book1.xlsx}] and the following status: [COMPLETED]
Below is my JobConfig
#Configuration
#EnableBatchProcessing
public class AddressExcelJobConfig {
#Bean
public BatchConfigurer configurer(EntityManagerFactory entityManagerFactory) {
return new CustomBatchConfigurer(entityManagerFactory);
}
#Bean
Step excelFileStep(ItemReader<AddressExcel> excelAddressReader,
ItemProcessor<AddressExcel, AddressExcel> excelAddressProcessor,
ItemWriter<AddressExcel> excelAddressWriter,
StepBuilderFactory stepBuilderFactory) {
return stepBuilderFactory.get("excelFileStep")
.<AddressExcel, AddressExcel>chunk(1)
.reader(excelAddressReader)
.processor(excelAddressProcessor)
.writer(excelAddressWriter)
.build();
}
#Bean
Job excelFileJob(JobBuilderFactory jobBuilderFactory,
#Qualifier("excelFileStep") Step excelAddressStep) {
return jobBuilderFactory.get("excelFileJob")
.incrementer(new RunIdIncrementer())
.flow(excelAddressStep)
.end()
.build();
}
}
Below is my AddressExcelReader
The late binding works fine, there is no error. I have tried loading the resource given the file name, in addition to creating a new ClassPathResource and FileSystemResource. All are giving me the same results.
#Component
#StepScope
public class AddressExcelReader implements ItemReader<AddressExcel> {
private PoiItemReader<AddressExcel> itemReader = new PoiItemReader<AddressExcel>();
#Override
public AddressExcel read()
throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
return itemReader.read();
}
public AddressExcelReader(#Value("#{jobParameters['file']}") String file, StorageService storageService) {
//Resource resource = storageService.loadAsResource(file);
//Resource testResource = new FileSystemResource("upload-dir/Book1.xlsx");
itemReader.setResource(new ClassPathResource("/upload-dir/Book1.xlsx"));
itemReader.setLinesToSkip(1);
itemReader.setStrict(true);
itemReader.setRowMapper(excelRowMapper());
}
public RowMapper<AddressExcel> excelRowMapper() {
BeanWrapperRowMapper<AddressExcel> rowMapper = new BeanWrapperRowMapper<>();
rowMapper.setTargetType(AddressExcel.class);
return rowMapper;
}
}
Below is my AddressExcelProcessor
#Component
public class AddressExcelProcessor implements ItemProcessor<AddressExcel, AddressExcel> {
private static final Logger log = LoggerFactory.getLogger(AddressExcelProcessor.class);
#Override
public AddressExcel process(AddressExcel item) throws Exception {
System.out.println("Converting " + item);
log.info("Convert {}", item);
return item;
}
}
Again, this is never coming into play (no logs generated). And if it matters, this is how I'm launching my job from a FileUploadController from a #PostMapping("/") to handle the file upload, which first stores the file, then runs the job:
#PostMapping("/")
public String handleFileUpload(#RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {
storageService.store(file);
try {
JobParameters jobParameters = new JobParametersBuilder()
.addString("file", file.getOriginalFilename().toString()).toJobParameters();
jobLauncher.run(job, jobParameters);
} catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException
| JobParametersInvalidException e) {
e.printStackTrace();
}
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded " + file.getOriginalFilename() + "!");
return "redirect:/";
}
And last by not least
Here is my AddressExcel POJO
import lombok.Data;
#Data
public class AddressExcel {
private String address1;
private String address2;
private String city;
private String state;
private String zip;
public AddressExcel() {}
}
UPDATE (10/13/2016)
From Nghia Do's comments, I also created my own RowMapper instead of using the BeanWrapper to see if that was the issue. Still the same results.
public class AddressExcelRowMapper implements RowMapper<AddressExcel> {
#Override
public AddressExcel mapRow(RowSet rs) throws Exception {
AddressExcel temp = new AddressExcel();
temp.setAddress1(rs.getColumnValue(0));
temp.setAddress2(rs.getColumnValue(1));
temp.setCity(rs.getColumnValue(2));
temp.setState(rs.getColumnValue(3));
temp.setZip(rs.getColumnValue(4));
return temp;
}
}
All it seems I needed was to add the following to my ItemReader:
itemReader.afterPropertiesSet();
itemReader.open(new ExecutionContext());

NullPointerException when I changed all my methods to static

Using Selenium w Java and Test NG (POM format) Switched everything from not static to static and changed everything accordingly, getting NullPointerException. It worked when everything was not static, but making everything static requires less code so I'd prefer to have it that way.
Here is my code.. while trying to paste my code for some reason it did not recognize the import statements as code so I just did not include them, but rest assured everything has been imported that is needed! :)
Package pages;
public class locationPage {
WebDriver driver;
static #FindBy (id="btn_bogota") WebElement chooseBogota;
static #FindBy (id="btn_medellin") WebElement chooseMedellin;
static #FindBy (xpath="//title") WebElement pageTitle;
public locationPage (WebDriver driver){
this.driver=driver;
PageFactory.initElements(driver, this);
}
public static void chooseLocation (String location) {
if (location.equals("Bogota"))
{
chooseBogota.click();
}
else if (location.equals("Medellin")){
chooseMedellin.click();
}
}
}
Package testcases;
public class selectLocation {
WebDriver driver;
#BeforeClass
public void setup() throws InterruptedException{
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://dev01.juanregala.com.co/");
//Generating Alert Using Javascript Executor
JavascriptExecutor javascript = (JavascriptExecutor) driver;
javascript.executeScript("alert('Select Location');");
Thread.sleep(2000);
driver.switchTo().alert().accept();
}
#AfterTest
public void quit(){
driver.quit();
}
#Test (priority=0)
public void location(){
locationPage.chooseLocation("Medellin");
}
}
It keeps giving me a NullPointerException referring to
chooseMedellin.click();
and
locationPage.chooseLocation("Medellin");
I am not really sure how else to describe my issue :( Please help!
You are getting a NullPointerException because the fields are not initialized. You can't use a page object in this way. Even if you could, you probably wouldn't want to since a page object is tied to a particular web driver and that would mean you could never use the same page object among multiple tests and run them in parallel.
Basically, the PageFactory only works on object instances. It won't initialize static fields and, even if it did, you are only calling the page factory from the constructor of your page and that is never being called since you only call a static method on that class.
You need to create an instance of the page object and then pass it to the PageFactory along with the driver that will be running the page object.
Simple example:
public class FooTest {
private WebDriver driver;
private FooPage page;
#BeforeMethod
public void setup() {
driver = new FirefoxDriver();
page = PageFactory.initElements(driver, FooPage.class);
}
#AfterMethod
public void tearDown() {
try {
driver.quit();
} catch ( Exception ignore ) { }
driver = null;
page = null;
}
#Test
public void testFoo() {
}
}
public class FooPage {
#FindBy(id="foo")
private WebElement fooElement;
public void clickFoo() {
fooElement.click();
}
}
Note the line:
page = PageFactory.initElements(driver, FooPage.class);
That method will actually call the default construct of FooPage. You can also instantiate the object yourself and pass it to the page factory like this:
page = new FooPage();
PageFactory.initElements(driver, page);

Capturing timing data from Junit tests on Eclipse

Running on Eclipse Galileo (3.5), I noticed my tests show the timing of each test run. Is there a way to capture and this information? Is there an API or is it stored in a result file?
Screenshot
http://ge.tt/3ylDyiq
We could use Rule to get time durations for each test method:
class TimeConsumeRule implements MethodRule {
#Override
public Statement apply(final Statement base, final FrameworkMethod method, Object target) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
long start = System.currentTimeMillis();
try {
base.evaluate();
} finally {
System.out.println(method.getName()+ " used "+ (System.currentTimeMillis() - start)+" ms;");
}
}
};
}
}
public class TimeConsume {
//Just declare customized Rule in your test case.
#Rule
public MethodRule rule = new TimeConsumeRule();
#Test
public void test1(){
//...
}
#Test
public void test2(){
//...
}
}