Is there any documentation about this? JUnit4 has #Rule and solution is straightforward. For JUnit5 I made a extension public class TestWatcher implements AfterTestExecutionCallback but I don't know what to put in #Override method.
I've managed to solve it. Method for screen capture is default one:
#Attachment(value = "{testName} - screenshot", type = "image/png")
private byte[] makeScreenshotOnFailure(String testName) {
return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
}
and TestWatcher (extension):
#Override
public void afterTestExecution(ExtensionContext extensionContext) throws Exception {
Object test = extensionContext.getRequiredTestInstance();
Field a = test.getClass().getDeclaredField("driver");
a.setAccessible(true);
driver = (WebDriver) a.get(test);
Method method = extensionContext.getRequiredTestMethod();
if (extensionContext.getExecutionException().isPresent()) {
makeScreenshotOnFailure(method.getName());
}
}
You can find a sample here. Is it a code from NoraUi Open Source Framework (Java + Selenium).
import org.openqa.selenium.TakesScreenshot;
final byte[] screenshot = ((TakesScreenshot) Context.getDriver()).getScreenshotAs(OutputType.BYTES);
Related
I have created below JUnit5 parameterized test with ArgumentsSource for loading arguments for the test:
public class DemoModelValidationTest {
public ParamsProvider paramsProvider;
public DemoModelValidationTest () {
try {
paramsProvider = new ParamsProvider();
}
catch (Exception iaex) {
}
}
#ParameterizedTest
#ArgumentsSource(ParamsProvider.class)
void testAllConfigurations(int configIndex, String a) throws Exception {
paramsProvider.executeSimulation(configIndex);
}
}
and the ParamsProvider class looks like below:
public class ParamsProvider implements ArgumentsProvider {
public static final String modelPath = System.getProperty("user.dir") + File.separator + "demoModels";
YAMLDeserializer deserializedYAML;
MetaModelToValidationModel converter;
ValidationRunner runner;
List<Configuration> configurationList;
List<Arguments> listOfArguments;
public ParamsProvider() throws Exception {
configurationList = new ArrayList<>();
listOfArguments = new LinkedList<>();
deserializedYAML = new YAMLDeserializer(modelPath);
deserializedYAML.load();
converter = new MetaModelToValidationModel(deserializedYAML);
runner = converter.convert();
configurationList = runner.getConfigurations();
for (int i = 0; i < configurationList.size(); i++) {
listOfArguments.add(Arguments.of(i, configurationList.get(i).getName()));
}
}
public void executeSimulation(int configListIndex) throws Exception {
final Configuration config = runner.getConfigurations().get(configListIndex);
runner.run(config);
runner.getReporter().consolePrintReport();
}
#Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return listOfArguments.stream().map(Arguments::of);
// return Stream.of(Arguments.of(0, "Actuator Power"), Arguments.of(1, "Error Logging"));
}}
In the provideArguments() method, the commented out code is working fine, but the first line of code
listOfArguments.stream().map(Arguments::of)
is returning the following error:
org.junit.platform.commons.PreconditionViolationException: Configuration error: You must configure at least one set of arguments for this #ParameterizedTest
I am not sure whether I am having a casting problem for the stream in provideArguments() method, but I guess it somehow cannot map the elements of listOfArguments to the stream, which can finally take the form like below:
Stream.of(Arguments.of(0, "Actuator Power"), Arguments.of(1, "Error Logging"))
Am I missing a proper stream mapping of listOfArguments?
provideArguments(…) is called before your test is invoked.
Your ParamsProvider class is instantiated by JUnit. Whatever you’re doing in desiralizeAndCreateValidationRunnerInstance should be done in the ParamsProvider constructor.
Also you’re already wrapping the values fro deserialised configurations to Arguments and you’re double wrapping them in providesArguments.
Do this:
#Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return listOfArguments.stream();
}}
I am trying to develop a IntelliJ plugin which provides a Language Server with help of lsp4intellij by ballerina.
Thing is, i've got a special condition: The list of completion items should be editable in runtime.
But I've not found any way to communicate new completionItems to the LanguageServer process once its running.
My current idea is to add an action to the plugin which builds a new jar and then restarts the server with the new jar, using the Java Compiler API.
The problem with that is, i need to get the source code from the plugin project including the gradle dependencies accessable from the running plugin... any ideas?
If your requirement is to modify the completion items (coming from the language server) before displaying them in the IntelliJ UI, you can do that by implementing the LSP4IntelliJ's
LSPExtensionManager in your plugin.
Currently, we do not have proper documentation for the LSP4IntelliJ's extension points but you can refer to our Ballerina IntelliJ plugin as a reference implementation, where it has implemented Ballerina LSP Extension manager to override/modify completion items at the client runtime in here.
For those who might stumble upon this - it is indeed possible to change the amount of CompletionItems the LanguageServer can provide during runtime.
I simply edited the TextDocumentService.java (the library I used is LSP4J).
It works like this:
The main function of the LanguageServer needs to be started with an additional argument, which is the path to the config file in which you define the CompletionItems.
Being called from LSP4IntelliJ it would look like this:
String[] command = new String[]{"java", "-jar",
"path\\to\\LangServer.jar", "path\\to\\config.json"};
IntellijLanguageClient.addServerDefinition(new RawCommandServerDefinition("md,java", command));
The path String will then be passed through to the Constructor of your CustomTextDocumentServer.java, which will parse the config.json in a new Timer thread.
An Example:
public class CustomTextDocumentService implements TextDocumentService {
private List<CompletionItem> providedItems;
private String pathToConfig;
public CustomTextDocumentService(String pathToConfig) {
this.pathToConfig = pathToConfig;
Timer timer = new Timer();
timer.schedule(new ReloadCompletionItemsTask(), 0, 10000);
loadCompletionItems();
}
#Override
public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completion(CompletionParams completionParams) {
return CompletableFuture.supplyAsync(() -> {
List<CompletionItem> completionItems;
completionItems = this.providedItems;
// Return the list of completion items.
return Either.forLeft(completionItems);
});
}
#Override
public void didOpen(DidOpenTextDocumentParams didOpenTextDocumentParams) {
}
#Override
public void didChange(DidChangeTextDocumentParams didChangeTextDocumentParams) {
}
#Override
public void didClose(DidCloseTextDocumentParams didCloseTextDocumentParams) {
}
#Override
public void didSave(DidSaveTextDocumentParams didSaveTextDocumentParams) {
}
private void loadCompletionItems() {
providedItems = new ArrayList<>();
CustomParser = new CustomParser(pathToConfig);
ArrayList<String> variables = customParser.getTheParsedItems();
for(String variable : variables) {
String itemTxt = "$" + variable + "$";
CompletionItem completionItem = new CompletionItem();
completionItem.setInsertText(itemTxt);
completionItem.setLabel(itemTxt);
completionItem.setKind(CompletionItemKind.Snippet);
completionItem.setDetail("CompletionItem");
providedItems.add(completionItem);
}
}
class ReloadCompletionItemsTask extends TimerTask {
#Override
public void run() {
loadCompletionItems();
}
}
}
I am using BrowserMob-Proxy inside a Selenium test suite. I would like to change the Referer for a few tests. I have added requestInterceptor from the 2.0 docs into our MyProxy class and while it does not generate an error the Referer is not changed.
For now, I am trying to get the requestInterceptor to work in the MyProxy class where the proxy is created. In the end, I would like to be able to specify the Referer in each test.
If anyone has suggestions on getting the requestInterceptor to work please let me know. Here is the MyProxy class. Please let me know if other code examples would be helpful to troubleshoot this.
import org.openqa.selenium.Proxy;
import net.lightbody.bmp.core.har.Har;
import net.lightbody.bmp.proxy.ProxyServer;
import net.lightbody.bmp.proxy.http.BrowserMobHttpRequest;
import net.lightbody.bmp.proxy.http.RequestInterceptor;
public class MyProxy {
private ProxyServer proxy;
private boolean initialized;
public Har endCapture() throws Exception {
Thread.sleep(15000);
return this.proxy.getHar();
}
public Proxy getSeleniumProxy() {
return this.proxy.seleniumProxy();
}
public boolean isInitialized() throws Exception {
return this.initialized;
}
public void start() throws Exception {
int proxyPort = Integer.parseInt(System.getProperty("proxyPort"));
this.proxy = new ProxyServer(proxyPort);
this.proxy.start();
this.proxy.setCaptureHeaders(true);
this.proxy.setCaptureContent(true);
this.proxy.addRequestInterceptor(new RequestInterceptor() {
#Override
public void process(BrowserMobHttpRequest request, Har har) {
request.getMethod().removeHeaders("Referer");
request.getMethod().addHeader("Referer", "http://www.google.com");
}
});
this.initialized = true;
}
public void startCapture() throws Exception{
this.proxy.newHar("MyHar");
}
public void stop() throws Exception {
this.proxy.stop();
this.initialized = false;
}
}
I think the key here is how to test the newly-added header, which is tricky to do manually.
I chose as a test-site: http://headers.cloxy.net/request.php, which simply logs the names and values of all request headers. Having first set up my proxy, I arranged a screenshot to be written after page request completed.
I was able to determine that:
#Override
public void process(BrowserMobHttpRequest req, Har har) {
req.getMethod().removeHeaders("Referer");
req.getMethod().addHeader("Referer", "http://www.google.xyz");
// Some extras
req.getMethod().addHeader("Foo_" + System.currentTimeMillis(), "Bar_" + new java.util.Date());
req.getMethod().setHeader("Lorem_" + System.currentTimeMillis(), "Ipsum_" + new java.util.Date());
}
... successfully adds all the specified headers in both BrowserMob 2.0.0 and 2.1 beta 5. I've confirmed this for each version in Firefox (45), Chrome (49), and PhantomJS.
So, in short:
The OP's header-adding syntax is perfectly fine.
setHeader also works as expected.
BMP version numbers do not affect this (but by all means upgrade to 2.1 as/when it is released)
Browsers do not affect this
Review this issue and see if it describes your problem.
Suggestion is to move to the latest version of BrowserMobProxy which is 2.1.0-beta-5.
I have the following feature file: MacroValidation.feature
#macroFilter
Feature: Separating out errors and warnings
Scenario: No errors or warnings when separating out error list
Given I have 0 macros
When I filter out errors and warnings for Macros
Then I need to have 0 errors
And I need to have 0 warnings
My definition files.
package com.test.definition;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import cucumber.runtime.java.StepDefAnnotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.powermock.api.mockito.PowerMockito.doReturn;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.spy;
#StepDefAnnotation
public class MacroValidationStepDefinitions {
private final MacroService macroService = spy(new MacroService());
private final LLRBusList busList = mock(LLRBusList.class);
private final List<String> errorList = new ArrayList<String>();
private final List<String> warningList = new ArrayList<String>();
#Before({"#macroFilter"})
public void setUp() {
errorList.addAll(Arrays.asList("error 1, error2, error 3"));
warningList.addAll(Arrays.asList("warning 1, warning 2, warning 3"));
}
#After({"#macroFilter"})
public void tearDown() {
errorList.clear();
warningList.clear();
}
#Given("^I have (\\d+) macros$")
public void i_have_macros(int input) {
doReturn(input).when(busList).size();
}
#When("^I filtered out errors and warnings for Macros$")
public void i_filtered_out_errors_and_warnings_for_Macros() {
macroService.separateErrorsAndWarning(busList, errorList, warningList);
}
#Then("^I need to have (\\d+) errors$")
public void i_need_to_have_errors(int numOfError) {
if (numOfError == 0) {
assertTrue(errorList.isEmpty());
} else {
assertEquals(errorList.size(), numOfError);
}
}
#Then("^I need to have (\\d+) warnings$")
public void i_need_to_have_warnings(int numOfWarnings) {
if (numOfWarnings == 0) {
assertTrue(warningList.isEmpty());
} else {
assertEquals(warningList.size(), numOfWarnings);
}
}
}
My unit test class.
#CucumberOptions(features = {"classpath:testfiles/MacroValidation.feature"},
glue = {"com.macro.definition"},
dryRun = false,
monochrome = true,
tags = "#macroFilter"
)
#RunWith(Cucumber.class)
public class PageMacroValidationTest {
}
When I execute the test, I get file definition not implemented warnings in the log.
Example log:
You can implement missing steps with the snippets below:
#Given("^I have (\\d+) macros$")
public void i_have_macros(int arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#When("^I filter out errors and warnings for Macros$")
public void i_filter_out_errors_and_warnings_for_Macros() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Then("^I need to have (\\d+) errors$")
public void i_need_to_have_errors(int arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Then("^I need to have (\\d+) warnings$")
public void i_need_to_have_warnings(int arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
I don't think file name should matter right?
It looks like Cucumber isn't finding your step defintion class. In your unit test class you say:
glue = {"com.macro.definition"}
However the step definition classes are in com.test.definition
Try changing that line to:
glue = {"com.test.definition"}
You may have to rebuild your project to pick up the change.
Also, Cucumber is sensitive to white space. If you try to make your runner or feature file pretty after having captured the snippets, you will get this problem.
Here's an example that drove me nuts for several hours while creating my first BDD. I had created the feature file and a skeleton runner which I ran and and captured the snippets. Then I prettified the feature file, and when I ran the runner got the errors.
Of course everything looked fine to my human brain, so the next few hours were spent in fruitless research here, and checking versions and bug lists. Finally I decided to compare the first two lines of the snippet to see what was different:
// #Then("^the test result is = \"([^\"]*)\"$")
// public void theTestResultIs(String ruleResult) throws Throwable {
#Then("^the test result is = \"([^\"]*)\"$")
public void theTestResultIs(String arg1) throws Throwable {
Doh!
Try to use all dependencies in POM.xml with io.cucumber group id which is the latest jars instead of info.cukes. After removing jars update the project with new imports and run the project.
Remember you have to replace all dependencies of info.cukes with io.cucumber
The following TestNG (6.3) test case generates the error "Invalid context for the recording of expectations"
#Listeners({ Initializer.class })
public final class ClassUnderTestTest {
private ClassUnderTest cut;
#SuppressWarnings("unused")
#BeforeMethod
private void initialise() {
cut = new ClassUnderTest();
}
#Test
public void doSomething() {
new Expectations() {
MockedClass tmc;
{
tmc.doMethod("Hello"); result = "Hello";
}
};
String result = cut.doSomething();
assertEquals(result, "Hello");
}
}
The class under test is below.
public class ClassUnderTest {
MockedClass service = new MockedClass();
MockedInterface ifce = new MockedInterfaceImpl();
public String doSomething() {
return (String) service.doMethod("Hello");
}
public String doSomethingElse() {
return (String) ifce.testMethod("Hello again");
}
}
I am making the assumption that because I am using the #Listeners annotation that I do not require the javaagent command line argument. This assumption may be wrong....
Can anyone point out what I have missed?
The JMockit-TestNG Initializer must run once for the whole test run, so using #Listeners on individual test classes won't work.
Instead, simply upgrade to JMockit 0.999.11, which works transparently with TestNG 6.2+, without any need to specify a listener or the -javaagent parameter (unless running on JDK 1.5).