Run parallel tests on Browserstack with Appium (java) + Cucumber + jUnit - junit

Using Browserstack tutorials (https://www.browserstack.com/app-automate/appium-junit) and sample project (https://github.com/browserstack/junit-appium-app-browserstack) I am struggling with setup of parallel tests.
Specifically, I need to run suirte with Cucumber.class (#RunWith(Cucumber.class)) for my tests to be read from scenarios, while Browserstack documentation tells me to run with Parameterized.class (public class Parallelized extends Parameterized).
The biggest problem I encounter is how to parse multiple device+os configurations to Browserstack, if you run the suite with Cucumber class.
My Runner class:
package step_definitions;
import org.junit.runner.RunWith;
import io.cucumber.junit.CucumberOptions;
import io.cucumber.junit.Cucumber;
#RunWith(Cucumber.class)
#CucumberOptions(features = {
"src/main/resources/FeatureFiles" }, dryRun = false, strict = false, monochrome = true, plugin = {
"html:target/cucumber", "json:target/cucumber.json" },
// glue = {"iOSAutomation/src/test/java/step_definitions"},
tags = { "#Login"})
public class RunTest {
}
Launcher:
package step_definitions;
import (...)
public class Launcher {
public static IOSDriver<IOSElement> driver;
public static WebDriverWait wait;
// Parallel BS tests
private static JSONObject config;
#Parameter(value = 0)
public static int taskID;
#Parameters
public static Iterable<? extends Object> data() throws Exception {
List<Integer> taskIDs = new ArrayList<Integer>();
if (System.getProperty("config") != null) {
JSONParser parser = new JSONParser();
config = (JSONObject) parser.parse(new FileReader("src/main/resources/conf/" + System.getProperty("config")));
int envs = ((JSONArray) config.get("environments")).size();
for (int i = 0; i < envs; i++) {
taskIDs.add(i);
}
}
return taskIDs;
}
#Before
public static void Launchapp(Scenario scenario) throws InterruptedException, FileNotFoundException, IOException, ParseException {
JSONArray envs = (JSONArray) config.get("environments");
DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability(MobileCapabilityType.AUTOMATION_NAME, "xcuitest");
caps.setCapability(MobileCapabilityType.PLATFORM_NAME, "iOS");
caps.setCapability("bundleId", bundleId);
caps.setCapability(MobileCapabilityType.APP, "useNewWDA");
caps.setCapability(MobileCapabilityType.APP, "clearSystemFiles");
caps.setCapability(MobileCapabilityType.APP, app);
caps.setCapability("browserstack.local", "false");
caps.setCapability("webkitResponseTimeout", "60000");
caps.setCapability("browserstack.localIdentifier", "Test123");
caps.setCapability("browserstack.appium_version", "1.9.1");
caps.setCapability("startIWDP", true);
caps.setCapability("instrumentApp", true);
caps.setCapability("webkitResponseTimeout", 70000);
Map<String, String> envCapabilities = (Map<String, String>) envs.get(taskID);
Iterator it = envCapabilities.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
caps.setCapability(pair.getKey().toString(), pair.getValue().toString());
}
driver = new IOSDriver<IOSElement>(
new URL("http://" + userName + ":" + accessKey + "#hub-cloud.browserstack.com/wd/hub"), caps);
sessionId = driver.getSessionId().toString();
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
wait = new WebDriverWait(driver, 30);
}
#After
public void tearDown(Scenario scenario) throws Exception {
driver.quit();
}
}
Parallelized.java:
package step_definitions;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.junit.runners.Parameterized;
import org.junit.runners.model.RunnerScheduler;
import io.cucumber.junit.Cucumber;
public class Parallelized extends Parameterized {
private static class ThreadPoolScheduler implements RunnerScheduler {
private ExecutorService executor;
public ThreadPoolScheduler() {
String threads = System.getProperty("junit.parallel.threads", "4");
int numThreads = Integer.parseInt(threads);
executor = Executors.newFixedThreadPool(numThreads);
}
#Override
public void finished() {
executor.shutdown();
try {
executor.awaitTermination(10, TimeUnit.MINUTES);
} catch (InterruptedException exc) {
throw new RuntimeException(exc);
}
}
#Override
public void schedule(Runnable childStatement) {
executor.submit(childStatement);
}
}
public Parallelized(Class klass) throws Throwable {
super(klass);
setScheduler(new ThreadPoolScheduler());
}
}
and config file:
{
"environments": [{
"device": "iPhone XR",
"os_version": "12"
}, {
"device": "iPhone 6S",
"os_version": "11"
}, {
"device": "iPhone XS",
"os_version": "13"
}, {
"device": "iPhone XS Max",
"os_version": "12"
}]
}
How to make it work? May I run this with Cucumber.class AND somehow incorporate methods from Parallelized.java?

You can use MakeFile where you can provide all the devices or platform capabilities and with cucumber-jvm-parallel-plugin the tests can be run parallel in Browserstack. This will be the easiest solution.
Sample MakeFile:
browserstack_parallel:
make -j bs_iPhoneXS bs_iPhoneX
bs_iPhoneXS:
mvn test -Dbs_local_testing=false -Dbs_device=iPhoneXS -Dbs_app=bs://0fb247cde17a979db4d7e5a521bc600af7620b63
bs_iPhoneX:
mvn test -Dbs_local_testing=false -Dbs_device=iPhoneX -Dbs_app=bs://0fb247cde17a979db4d7e5a521bc600af7620b63
You can run MakeFile from terminal by typing make browserstack_parallel

Related

Reading Very Complex JSON using Spring Batch

My objective is to read a very complex JSON using Spring Batch. Below is the sample JSON.
{
"order-info" : {
"order-number" : "Test-Order-1"
"order-items" : [
{
"item-id" : "4144769310"
"categories" : [
"ABCD",
"DEF"
],
"item_imag" : "http:// "
"attributes: {
"color" : "red"
},
"dimensions" : {
},
"vendor" : "abcd",
},
{
"item-id" : "88888",
"categories" : [
"ABCD",
"DEF"
],
.......
I understand that I would need to create a Custom ItemReader to parse this JSON.
Kindly provide me some pointers. I am really clueless.
I am now not using CustomItemReader. I am using Java POJOs. My JsonItemReader is as per below:
#Bean
public JsonItemReader<Trade> jsonItemReader() {
ObjectMapper objectMapper = new ObjectMapper();
JacksonJsonObjectReader<Trade> jsonObjectReader =
new JacksonJsonObjectReader<>(Trade.class);
jsonObjectReader.setMapper(objectMapper);
return new JsonItemReaderBuilder<Trade>()
.jsonObjectReader(jsonObjectReader)
.resource(new ClassPathResource("search_data_1.json"))
.name("tradeJsonItemReader")
.build();
}
The exception which I now get is :
java.lang.IllegalStateException: The Json input stream must start with an array of Json objects
From similar posts in this forum I understand that I need to use JsonObjectReader. "You can implement it to read a single json object and use it with the JsonItemReader (either at construction time or using the setter)".
How can I do this either # construction time or using setter? Please share some code snippet for the same.
The delegate of MultiResourceItemReader should still be a JsonItemReader. You just need to use a custom JsonObjectReader with the JsonItemReader instead of JacksonJsonObjectReader. Visually, this would be: MultiResourceItemReader -- delegates to --> JsonItemReader -- uses --> your custom JsonObjectReader.
Could you please share a code snippet for the above?
JacksonJsonItemReader is meant to parse from a root node that is already and array node, so it expects your json to start with '['.
If you desire to parse a complex object - in this case, one that have many parent nodes/properties before it gets to the array - you should write a reader. It is really simple to do it and you can follow JacksonJsonObjectReader's structure. Here follows and example of a generic reader for complex object with respective unit tests.
The unit test
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.springframework.core.io.ByteArrayResource;
import com.example.batch_experiment.dataset.Dataset;
import com.example.batch_experiment.dataset.GenericJsonObjectReader;
import com.example.batch_experiment.json.InvalidArrayNodeException;
import com.example.batch_experiment.json.UnreachableNodeException;
import com.fasterxml.jackson.databind.ObjectMapper;
#RunWith(BlockJUnit4ClassRunner.class)
public class GenericJsonObjectReaderTest {
GenericJsonObjectReader<Dataset> reader;
#Before
public void setUp() {
reader = new GenericJsonObjectReader<Dataset>(Dataset.class, "results");
}
#Test
public void shouldRead_ResultAsRootNode() throws Exception {
reader.open(new ByteArrayResource("{\"result\":{\"results\":[{\"id\":\"a\"}]}}".getBytes()) {});
Assert.assertTrue(reader.getDatasetNode().isArray());
Assert.assertFalse(reader.getDatasetNode().isEmpty());
}
#Test
public void shouldIgnoreUnknownProperty() throws Exception {
String jsonStr = "{\"result\":{\"results\":[{\"id\":\"a\", \"aDifferrentProperty\":0}]}}";
reader.open(new ByteArrayResource(jsonStr.getBytes()) {});
Assert.assertTrue(reader.getDatasetNode().isArray());
Assert.assertFalse(reader.getDatasetNode().isEmpty());
}
#Test
public void shouldIgnoreNullWithoutQuotes() throws Exception {
String jsonStr = "{\"result\":{\"results\":[{\"id\":\"a\",\"name\":null}]}}";
try {
reader.open(new ByteArrayResource(jsonStr.getBytes()) {});
Assert.assertTrue(reader.getDatasetNode().isArray());
Assert.assertFalse(reader.getDatasetNode().isEmpty());
} catch (Exception e) {
Assert.fail(e.getMessage());
}
}
#Test
public void shouldThrowException_OnNullNode() throws Exception {
boolean exceptionThrown = false;
try {
reader.open(new ByteArrayResource("{}".getBytes()) {});
} catch (UnreachableNodeException e) {
exceptionThrown = true;
}
Assert.assertTrue(exceptionThrown);
}
#Test
public void shouldThrowException_OnNotArrayNode() throws Exception {
boolean exceptionThrown = false;
try {
reader.open(new ByteArrayResource("{\"result\":{\"results\":{}}}".getBytes()) {});
} catch (InvalidArrayNodeException e) {
exceptionThrown = true;
}
Assert.assertTrue(exceptionThrown);
}
#Test
public void shouldReadObjectValue() {
try {
reader.setJsonParser(new ObjectMapper().createParser("{\"id\":\"a\"}"));
Dataset dataset = reader.read();
Assert.assertNotNull(dataset);
Assert.assertEquals("a", dataset.getId());
} catch (Exception e) {
Assert.fail(e.getMessage());
}
}
}
And the reader:
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.json.JsonObjectReader;
import org.springframework.core.io.Resource;
import com.example.batch_experiment.json.InvalidArrayNodeException;
import com.example.batch_experiment.json.UnreachableNodeException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
/*
* This class follows the structure and functions similar to JacksonJsonObjectReader, with
* the difference that it expects a object as root node, instead of an array.
*/
public class GenericJsonObjectReader<T> implements JsonObjectReader<T>{
Logger logger = Logger.getLogger(GenericJsonObjectReader.class.getName());
ObjectMapper mapper = new ObjectMapper();
private JsonParser jsonParser;
private InputStream inputStream;
private ArrayNode targetNode;
private Class<T> targetType;
private String targetPath;
public GenericJsonObjectReader(Class<T> targetType, String targetPath) {
super();
this.targetType = targetType;
this.targetPath = targetPath;
}
public JsonParser getJsonParser() {
return jsonParser;
}
public void setJsonParser(JsonParser jsonParser) {
this.jsonParser = jsonParser;
}
public ArrayNode getDatasetNode() {
return targetNode;
}
/*
* JsonObjectReader interface has an empty default method and must be implemented in this case to set
* the mapper and the parser
*/
#Override
public void open(Resource resource) throws Exception {
logger.info("Opening json object reader");
this.inputStream = resource.getInputStream();
JsonNode jsonNode = this.mapper.readTree(this.inputStream).findPath(targetPath);
if (!jsonNode.isMissingNode()) {
this.jsonParser = startArrayParser(jsonNode);
logger.info("Reader open with parser reference: " + this.jsonParser);
this.targetNode = (ArrayNode) jsonNode; // for testing purposes
} else {
logger.severe("Couldn't read target node " + this.targetPath);
throw new UnreachableNodeException();
}
}
#Override
public T read() throws Exception {
try {
if (this.jsonParser.nextToken() == JsonToken.START_OBJECT) {
T result = this.mapper.readValue(this.jsonParser, this.targetType);
logger.info("Object read: " + result.hashCode());
return result;
}
} catch (IOException e) {
throw new ParseException("Unable to read next JSON object", e);
}
return null;
}
/**
* Creates a new parser from an array node
*/
private JsonParser startArrayParser(JsonNode jsonArrayNode) throws IOException {
JsonParser jsonParser = this.mapper.getFactory().createParser(jsonArrayNode.toString());
if (jsonParser.nextToken() == JsonToken.START_ARRAY) {
return jsonParser;
} else {
throw new InvalidArrayNodeException();
}
}
#Override
public void close() throws Exception {
this.inputStream.close();
this.jsonParser.close();
}
}

Spring webflux Netty: How to expose proto as json endpoints without duplication of code?

Use-case:
Developers/I, want to only implement a Protobuf implementation (binary protocol). However, I need a way to add config, so, the same implementation is exposed as rest/json api as well -- without code duplication.
I have proto endpoints exposed. I also want consumers to post json equivalent of those proto objects and return/receive json equivalent of the results with type info (Pojo?). The type info helps with OpenAPI / Swagger documentation too!
What are the most elegant/simple ways to achieve that without code duplication?
Any example github code that achieves that would be helpful.
Note: This is for webflux & netty - no tomcat.
ProtobufJsonFormatHttpMessageConverter - works for tomcat, does not work for netty. A working example code would be great.
I was messing around with this and ended up with this. Nothing else worked for me.
Using protov3 and setting a protobuf like this
syntax = "proto3";
option java_package = "com.company";
option java_multiple_files = true;
message CreateThingRequest {
...
message CreateThingResponse {
....
I can scan for the protobuf files by setting app.protoPath in my application.properties
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.google.common.reflect.ClassPath;
import com.google.protobuf.Message;
import com.google.protobuf.util.JsonFormat;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.reactive.config.WebFluxConfigurer;
#Configuration
public class WebConfig implements WebFluxConfigurer {
#Value("${app.protoPath:com.}")
private String protoPath;
#Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.defaultCodecs().jackson2JsonEncoder(
new Jackson2JsonEncoder(Jackson2ObjectMapperBuilder.json().serializerByType(
Message.class, new JsonSerializer<Message>() {
#Override
public void serialize(Message value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
String str = JsonFormat.printer().omittingInsignificantWhitespace().print(value);
gen.writeRawValue(str);
}
}
).build())
);
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
Map<Class<?>, JsonDeserializer<?>> deserializers = new HashMap<>();
try {
for (final ClassPath.ClassInfo info : ClassPath.from(loader).getTopLevelClasses()) {
if (info.getName().startsWith(protoPath)) {
final Class<?> clazz = info.load();
if (!Message.class.isAssignableFrom(clazz)) {
continue;
}
#SuppressWarnings("unchecked") final Class<Message> proto = (Class<Message>) clazz;
final JsonDeserializer<Message> deserializer = new CustomJsonDeserializer() {
#Override
public Class<Message> getDeserializeClass() {
return proto;
}
};
deserializers.put(proto, deserializer);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
configurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(Jackson2ObjectMapperBuilder.json().deserializersByType(deserializers).build()));
}
private abstract static class CustomJsonDeserializer extends JsonDeserializer<Message> {
abstract Class<? extends Message> getDeserializeClass();
#Override
public Message deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
Message.Builder builder = null;
try {
builder = (Message.Builder) getDeserializeClass()
.getDeclaredMethod("newBuilder")
.invoke(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
JsonFormat.parser().merge(jp.getCodec().readTree(jp).toString(), builder);
return builder.build();
}
}
}
Then I just use the object types in the returns;
#PostMapping(
path = "/things",
consumes = {MediaType.APPLICATION_JSON_VALUE, "application/x-protobuf"},
produces = {MediaType.APPLICATION_JSON_VALUE, "application/x-protobuf"})
Mono<CreateThingResponse> createThing(#RequestBody CreateThingRequest request);
With https://github.com/innogames/springfox-protobuf you can get the responses to show in swagger but the requests still aren't showing for me.
You'll have to excuse the messy Java I'm a little rusty.
I needed to support json and the following code helped
#Bean
public WebFluxConfigurer webFluxConfigurer() {
return new WebFluxConfigurer() {
#Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
ObjectMapper mapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.registerModule(new ProtobufModule());
configurer.customCodecs().register(new Jackson2JsonEncoder(mapper));
configurer.customCodecs().register(new Jackson2JsonDecoder(mapper));
}
};
}
Try adding ProtoEncoder in your WebFlux config:
#EnableWebFlux
public class MyConfig implements WebFluxConfigurer {
#Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.customCodecs().register(new ProtobufEncoder());
}
}
Then in your request mapping return the proto object:
#GetMapping (produces = "application/x-protobuf")
public MyProtoObject lookup() {
return new MyProtoObject();
}
Furthermore, if you want to serialize the proto object into JSON and return String, then have a look at com.googlecode.protobuf-java-format:protobuf-java-format library and JsonFormat::printToString capability (https://code.google.com/archive/p/protobuf-java-format/):
#GetMapping
public String lookup() {
return new JsonFormat().printToString(new MyProtoObj());
}
Since version 4.1 spring provides org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter for reading and writing protos as Json.
However, If you are using Spring 5.x and Protobuf 3.x there is org.springframework.http.converter.protobuf.ProtobufJsonFormatHttpMessageConverter for more explicit conversion of Json.
This documentation should help you:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/converter/protobuf/ProtobufHttpMessageConverter.html
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/converter/protobuf/ProtobufJsonFormatHttpMessageConverter.html

Test with JUnit an request

I wanna to test an request with JUnit with an request like this but RxUtils.applySchedulersAndErrorMapper() return null. Is any possibilities to test that?
override fun onContinueClicked(phoneNumber: String) {
mView.showLoading()
mUserService.checkUserApprovedStatus(phoneNumber)
.compose(RxUtils.applySchedulersAndErrorMapper())
.subscribe({ response ->
//Success
}, { error ->
//Error
})
}
here is where I setup the presenter and mUserService for presenter
#Mock
private PhoneContract.View view;
#Mock
private UserService userService;
#Before
public void setup() {
presenter = new PhonePresenter(this.view);
presenter.mUserService = userService;
}
here is the test method
#Test
public void onContinueClicked_SendJustNumbers() {
String phoneNumber = "(01234567890)";
// when
presenter.onContinueClicked(phoneNumber);
// then
verify(view, times(1)).showLoading();
}
and here is the RXUtils class:
class RxUtils {
companion object {
#SuppressLint("CheckResult")
fun <E> applySchedulersAndErrorMapper(): ObservableTransformer<E, E> {
return ObservableTransformer { o ->
o.flatMap(Function<E, ObservableSource<E>> { element ->
val genericResponse = element as GenericResponse<*>
#Suppress("UNCHECKED_CAST")
return#Function Observable.just(genericResponse as E)
}).onErrorResumeNext(Function<Throwable, ObservableSource<E>> { t ->
if (t is ApiException) {
return#Function Observable.error(t)
}
var genericResponse: GenericResponse<*>? = null
return#Function Observable.error(ApiException(t.message ?: "", genericResponse?.result ?: Result()))
})
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
}
}
}
}
Here is the stacktrace where I receive null for RxUtils.applySchedulersAndErrorMapper()
java.lang.NullPointerException
If it relates to the SDK, it probably won't work in a unit test. You didn't include your imports, so it's impossible to tell at a glance, but I know from experience that you can't use this in a unit test
AndroidSchedulers.mainThread()
You need to replace that with, say, Schedulers.trampoline()
Example of how to set a custom scheduler for testing
Note, this is only an example, and there are other valid solutions.
class RxUtils {
companion object {
// add this
#VisibleForTesting var mainScheduler = AndroidSchedulers.mainThread()
#VisibleForTesting var ioScheduler = Schedulers.io()
#SuppressLint("CheckResult")
fun <E> applySchedulersAndErrorMapper(): ObservableTransformer<E, E> {
return ObservableTransformer { o ->
o.flatMap(Function<E, ObservableSource<E>> { element ->
val genericResponse = element as GenericResponse<*>
#Suppress("UNCHECKED_CAST")
return#Function Observable.just(genericResponse as E)
}).onErrorResumeNext(Function<Throwable, ObservableSource<E>> { t ->
if (t is ApiException) {
return#Function Observable.error(t)
}
var genericResponse: GenericResponse<*>? = null
return#Function Observable.error(ApiException(t.message ?: "", genericResponse?.result ?: Result()))
})
.observeOn(mainScheduler)
.subscribeOn(ioScheduler)
}
}
}
}
And in your test:
#Before fun setup() {
RxUtils.mainScheduler = Schedulers.trampoline()
RxUtils.ioScheduler = Schedulers.trampoline()
}
#After fun teardown() {
RxUtils.mainScheduler = AndroidSchedulers.mainThread()
RxUtils.ioScheduler = Schedulers.io()
}
EDIT in response to updated post with more information on test
First of all, you should post WAY MORE CODE. It's frustrating having to pull it out of you by dribs and drabs. Anyway. You have the following:
#Mock
private UserService userService;
That creates a mock UserService, sure, but it doesn't stub anything. When you call userService.anyFunctionAtAll(), it will return null by default. There's your NPE. You have to stub it. For example:
Mockito.when(userService.anyFunctionAtAll()).thenReturn(somePredeterminedValue)
Please refer to the Mockito website for more information.

Jmeter: junit request is not giving results

I am using junit request in jmeter to get the performance result of the scripts. When I run the script it is not giving any error however it is not giving the results.
I am adding the jav source code of junit request and also will provide the output screen.
please check what is the issue as i have added the required plugins and jar into the same
package com.seleniummaster.jmeterjunit;
import static org.junit.Assert.*;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.MarionetteDriver;
public class LoginTest {
private WebDriver driver;
private String baseUrl;
private boolean acceptNextAlert = true;
private StringBuffer verificationErrors = new StringBuffer();
#Before
public void setUp() throws Exception {
//use Firefox driver
// driver = new FirefoxDriver();
//use demo.mahara.org site for testing
System.setProperty("webdriver.gecko.driver",
"D:\\Seleniumdriver\\geckodriver.exe");
driver = new MarionetteDriver();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
baseUrl = "http://demo.mahara.org";
//timeout if site page does not load in 30 seconds
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#After
public void tearDown() throws Exception {
//quit the test
driver.quit();
String verificationErrorString = verificationErrors.toString();
if (!"".equals(verificationErrorString)) {
fail(verificationErrorString);
}
}
#Test
public void test() throws InterruptedException {
//navigate to base url
driver.get(baseUrl + "/");
//clear username filed
driver.findElement(By.id("login_login_username")).clear();
//enter user name
driver.findElement(By.id("login_login_username")).sendKeys("student1");
//clear password
driver.findElement(By.id("login_login_password")).clear();
//enter password
driver.findElement(By.id("login_login_password")).sendKeys("Testing1");
//click on submit button
driver.findElement(By.id("login_submit")).click();
//assert the Dashboard link text
for (int second = 0;; second++) {
if (second >= 60) fail("timeout");
try { if (isElementPresent(By.linkText("Dashboard"))) break; } catch (Exception e) {}
Thread.sleep(1000);
}
assertEquals("Dashboard", driver.findElement(By.linkText("Dashboard")).getText());
}
private boolean isElementPresent(By by) {
try {
driver.findElement(by);
return true;
} catch (NoSuchElementException e) {
return false;
}
}
private boolean isAlertPresent() {
try {
driver.switchTo().alert();
return true;
} catch (NoAlertPresentException e) {
return false;
}
}
private String closeAlertAndGetItsText() {
try {
Alert alert = driver.switchTo().alert();
String alertText = alert.getText();
if (acceptNextAlert) {
alert.accept();
} else {
alert.dismiss();
}
return alertText;
} finally {
acceptNextAlert = true;
}
}
}
I recently faced the same issue. I checked below two boxes in the Junit Request page on Jmeter UI.
Append assertion errors
Append runtime exception
After this when I executed the test again, I found the error in the "View Results Tree" listener under Response Message field.
Hope this helps.
Please try making all private variables as public. It may happen that JMeter is not able access those.
Also, refer console on JMeter, it should show you errors/exceptions.

Ehcache hangs in test

I am in the process of rewriting a bottle neck in the code of the project I am on, and in doing so I am creating a top level item that contains a self populating Ehcache. I am attempting to write a test to make sure that the basic call chain is established, but when the test executes it hands when retrieving the item from the cache.
Here are the Setup and the test, for reference mocking is being done with Mockito:
#Before
public void SetUp()
{
testCache = new Cache(getTestCacheConfiguration());
recordingFactory = new EntryCreationRecordingCache();
service = new Service<Request, Response>(testCache, recordingFactory);
}
#Test
public void retrievesResultsFromSuppliedCache()
{
ResultType resultType = mock(ResultType.class);
Response expectedResponse = mock(Response.class);
addToExpectedResults(resultType, expectedResponse);
Request request = mock(Request.class);
when(request.getResultType()).thenReturn(resultType);
assertThat(service.getResponse(request), sameInstance(expectedResponse));
assertTrue(recordingFactory.requestList.contains(request));
}
private void addToExpectedResults(ResultType resultType,
Response response) {
recordingFactory.responseMap.put(resultType, response);
}
private CacheConfiguration getTestCacheConfiguration() {
CacheConfiguration cacheConfiguration = new CacheConfiguration("TEST_CACHE", 10);
cacheConfiguration.setLoggingEnabled(false);
return cacheConfiguration;
}
private class EntryCreationRecordingCache extends ResponseFactory{
public final Map<ResultType, Response> responseMap = new ConcurrentHashMap<ResultType, Response>();
public final List<Request> requestList = new ArrayList<Request>();
#Override
protected Map<ResultType, Response> generateResponse(Request request) {
requestList.add(request);
return responseMap;
}
}
Here is the ServiceClass
public class Service<K extends Request, V extends Response> {
private Ehcache cache;
public Service(Ehcache cache, ResponseFactory factory) {
this.cache = new SelfPopulatingCache(cache, factory);
}
#SuppressWarnings("unchecked")
public V getResponse(K request)
{
ResultType resultType = request.getResultType();
Element cacheEntry = cache.get(request);
V response = null;
if(cacheEntry != null){
Map<ResultType, Response> resultTypeMap = (Map<ResultType, Response>) cacheEntry.getValue();
try{
response = (V) resultTypeMap.get(resultType);
}catch(NullPointerException e){
throw new RuntimeException("Result type not found for Result Type: " + resultType);
}catch(ClassCastException e){
throw new RuntimeException("Incorrect Response Type for Result Type: " + resultType);
}
}
return response;
}
}
And here is the ResponseFactory:
public abstract class ResponseFactory implements CacheEntryFactory{
#Override
public final Object createEntry(Object request) throws Exception {
return generateResponse((Request)request);
}
protected abstract Map<ResultType,Response> generateResponse(Request request);
}
After wrestling with it for a while, I discovered that the cache wasn't being initialized. Creating a CacheManager and adding the cache to it resolved the problem.
I also had a problem with EHCache hanging, although only in a hello-world example. Adding this to the end fixed it (the application ends normally).
CacheManager.getInstance().removeAllCaches();
https://stackoverflow.com/a/20731502/2736496