Run the JUnitServllet for integration testing in Adobe cq5 - aem

My question is for the JUnitServlet for integration testing in Adobe cq5. When it runs the tests and if there is a mistake in the test method it shows only error messages from his side. How can we see the messages that we write in the test method assertations.
For example:
If I have several "assertNotNull" in the test method and if the test fails the servlet shows me such a result:
Test finished: () : Null
I tried to enter in depth:
Test selector: RequestParser, testSelector [testClass], methodName [testMethod], extension [html]
but again it runs the whole class with thests.
Can I somehow run just one testing method from the testing class and see the messages from the assertations with this servlet? Thanks!

You might try structuring your assertions inside a try/catch block--at least initially--where you can print out additional info if it fails. I've found this to provide more useful info when I have a problem in the test itself that is getting masked in the unit test output. If that is the issue perhaps you won't need to narrow in on a single test.
#Test
public void testYourTestName() throws Exception {
try {
//Code to prepare the object to be tested
assertNull("This is my null test", objectToBeTested);
} catch (Exception e) {
String failureMessage = "\n" + e.toString() + "\n";
for (StackTraceElement stackLine : e.getStackTrace()) {
failureMessage += (stackLine.toString() + "\n");
}
fail("Error: " + failureMessage);
}
}
Or, you could use an assertEquals test which I have found to have a little more helpful display, such as this:
assertEquals(null, objectToBeTested);
If the assertEquals above fails, you get output such as this:
testMyTestName(com.myCompany.myApp.myPath.myTests): expected:<null>
but was:<java.lang.Object#5c9e4d73>
BTW, I don't know how to run just one of the tests that exists in some class, but as you have found, you can narrow it down to run all the tests in a particular class. To run the tests found in the SomeTestClass in the com.myCompany.myApp.myPath namespace:
http://localhost:4502/system/sling/junit/com.myCompany.myApp.myPath.SomeTestClass.html

Related

Test that an exception is handled correctly with pytest

I have a block of try-exception code and I want to test if the block works properly? I wonder if there is a way to test this block with a unit test using pylint? This is the snipent I have:
class data_type(Enum):
SESSIONS = 0
RUNS = 1
def find_filter(data_type)
try:
if data_type.name == 'SESSIONS':
return {}
elif data_type.name == 'RUNS':
#Filter out rerun jobs
filter = {
"filter":{
"attName":"is_rerun",
"operand":"IN",
"#c":".InFilter",
"values":["FALSE"]
}
}
return filter
except AttributeError as erro:
loghandler.critical('Error in creating count query: {}'.format(erro))
I want to test if the data_type is not a valid enum member, the exception catches it before the execution goes to if statement. For example if:
find_filter('')
is called I like to see that the except AttributeError as erro captures the error and the error is logged.
Is there a way to do that?
PS: I know with pytest.raises() I can test if a raised error is really raised? But as far as I understand pytest.raises() does not work for testing the exception block of a try-exception case.
Any suggestion please?
Thanks.

Remove failure message from multiple assertion failure in NUnit

I have configured my tests to retry up to x number of times in the event of a failure, to ensure the failure is legitimate and not a fluke during the run. I do not log the error message on the initial failure.
However, I am noticing that if I am running a test, the first test fails, and then the second test passes and I check for any assertion failures via TestContext.CurrentContext.Result.Message and notice the first iteration failure is logged and my test is shown as failed, even though the test passed during the second iteration. If both tests fail, I will receive a "Multiple failures or warnings in test."
I would like to retain the final run's failure only vs all the failures for all the iterations. Is there a way to remove the initial failure from the TestContext.CurrentCOntext.Result.Message?
Edit: I am using NUnit v 3.10.1 and when I downgraded to v.3.4.0 I got the experience I desired without any modification to my code.
Use NUnit's [Retry(5)] attribute on your test to retry the test if it fails. Workarounds like in the link you posted depend on the undocumented internal behavior of NUnit that may change between releases.
Update based on your comment below, if you need to handle unexpected exceptions, wrap the flaky code that might throw in a try/catch block, then do your assertions outside of that block.
[Test]
[Retry(5)]
public void TestFlakyMethod()
{
int result = 0;
try
{
result = FlakyAdd(2, 2);
}
catch(Exception ex)
{
Assert.Fail($"Test failed with unexpected exception, {ex.Message}");
}
Assert.That(result, Is.EqualTo(4));
}
int FlakyAdd(int x, int y)
{
var rand = new Random();
if (rand.NextDouble() > 0.5)
throw new ArgumentOutOfRangeException();
return x + y;
}
Adding to the above, you can also use Assert.DoesNotThrow, it is a bit cleaner and easier to write.
[Test]
[Retry(5)]
public void TestFlakyMethod()
{
int result = 0;
Assert.DoesNotThrow(() => {{
result = FlakyAdd(2, 2);
});
Assert.That(result, Is.EqualTo(4));
}

Strange timeout with ScalaTest's Selenium DSL

I'm writing Selenium tests with ScalaTest's Selenium DSL and I'm running into timeouts I can't explain. To make matters more complicated, they only seem to happen some of the time.
The problem occurs whenever I access an Element after a page load or some Javascript rendering. It looks like this:
click on "editEmployee"
eventually {
textField(name("firstName")).value = "Steve"
}
My PatienceConfig is configured like this:
override implicit val patienceConfig: PatienceConfig =
PatienceConfig(timeout = Span(5, Seconds), interval = Span(50, Millis))
The test fails with the following error:
- should not display the old data after an employee was edited *** FAILED ***
The code passed to eventually never returned normally. Attempted 1 times over 10.023253653000001 seconds.
Last failure message: WebElement 'firstName' not found.. (EditOwnerTest.scala:24)
It makes sense that it doesn't succeed immediately, because the click causes some rendering, and the textfield may not be available right away. However, it shouldn't take 10 seconds to make an attempt to find it, right?
Also, I find it very interesting that the eventually block tried it only once, and that it took almost precisely 10 seconds. This smells like a timeout occurred somewhere, and it's not my PatienceConfig, because that was set to time out after 5 seconds.
With this workaround, it does work:
click on "editEmployee"
eventually {
find(name("firstName")).value // from ScalaTest's `OptionValues`
}
textField(name("firstName")).value = "Steve"
I did some digging in the ScalaTest source, and I've noticed that all calls that have this problem (it's not just textField), eventually call webElement at some point. The reason why the workaround works, is because it doesn't call webElement. webElement is defined like this:
def webElement(implicit driver: WebDriver, pos: source.Position = implicitly[source.Position]): WebElement = {
try {
driver.findElement(by)
}
catch {
case e: org.openqa.selenium.NoSuchElementException =>
// the following is avoid the suite instance to be bound/dragged into the messageFun, which can cause serialization problem.
val queryStringValue = queryString
throw new TestFailedException(
(_: StackDepthException) => Some("WebElement '" + queryStringValue + "' not found."),
Some(e),
pos
)
}
}
I've copied that code into my project and played around with it, and it looks like constructing and/or throwing the exception is where most of the 10 seconds are spent.
(EDIT Clarification: I've actually seen the code actually spend its 10 seconds inside the catch block. The implicit wait is set to 0, and besides, if I remove the catch block everything simply works as expected.)
So my question is, what can I do to avoid this strange behaviour? I don't want to have to insert superfluous calls to find all the time, because it's easily forgotten, especially since, as I said, the error occurs only some of the time. (I haven't been able to determine when the behaviour occurs and when it doesn't.)
It is clear that the textField(name("firstName")).value = "Steve" ends up calling the WebElement as you have found out.
Since the issue in the op is happening where ever web elements are involved (which in turn implies that webdriver is involved), I think it is safe to assume that the issue is related to the implicit wait on the Web driver.
implicitlyWait(Span(0, Seconds))
The above should ideally fix the issue. Also, making implicit wait to be 0 is a bad practice. Any web page might have some loading issues. The page load is handled by Selenium outside its wait conditions. But slow element load (may be due to ajax calls) could result in failure. I usually keep 10 seconds as my standard implicit wait. For scenarios which require more wait, explicit waits can be used.
def implicitlyWait(timeout: Span)(implicit driver: WebDriver): Unit = {
driver.manage.timeouts.implicitlyWait(timeout.totalNanos, TimeUnit.NANOSECONDS)
}
Execution Flow:
name("firstName") ends up having value as Query {Val by = By.className("firstName") }.
def name(elementName: String): NameQuery = new NameQuery(elementName)
case class NameQuery(queryString: String) extends Query { val by = By.name(queryString) }
Query is fed to the textField method which calls the Query.webElement as below.
def textField(query: Query)(implicit driver: WebDriver, pos: source.Position): TextField = new TextField(query.webElement)(pos)
sealed trait Query extends Product with Serializable {
val by: By
val queryString: String
def webElement(implicit driver: WebDriver, pos: source.Position = implicitly[source.Position]): WebElement = {
try {
driver.findElement(by)
}
catch {
case e: org.openqa.selenium.NoSuchElementException =>
// the following is avoid the suite instance to be bound/dragged into the messageFun, which can cause serialization problem.
val queryStringValue = queryString
throw new TestFailedException(
(_: StackDepthException) => Some("WebElement '" + queryStringValue + "' not found."),
Some(e),
pos
)
}
}
}
I don't know ScalaTest's specifics, but such strange timeouts usually occur when you're mixing up implicit and explicit waits together.
driver.findElement uses implicit waits internally. And depending on specified explicit waits timeout, you may face with summing both together.
Ideally, implicit waits should be set to 0 to avoid such issues.

Twitter Logging and Scala Custom Handlers

I'm using Twitter's logging framework in Scala, version 6.5.0.
I've written a toy usage example:
import com.twitter.logging._
object TestFormatter extends Formatter
{
override def format( record : java.util.logging.LogRecord) = "TEST %s> ".format( record.getLevel.getName ) + formatText(record) + lineTerminator
}
object Main extends App
{
override def main( args : Array[String] ) : Unit =
{
// obtain a logger
val log = Logger.get( getClass )
// clear any existing message handlers
Logger.clearHandlers
// add a new handler, using my toy formatter
log.addHandler( ConsoleHandler( TestFormatter, Some( Level.DEBUG ) )() )
// log a couple of test messages
log.debug( "DEBUG LOG" )
log.warning( "WARNING LOG" )
}
}
The class TestFormatter isn't really necessary, but will help to highlight my problem. I'm pretty sure that what I should see from this by way of output from this code is something along the lines of:
TEST DEBUG> DEBUG LOG
TEST WARNING> WARNING LOG
However, what I actually get is:
TEST WARNING> WARNING LOG
WARNING: WARNING LOG
This raises two issues:
Why has some other handler also handled my warning message, despite me clearing existing handlers? - SOLVED
Why, when I've set the level of my logger to debug, has the message I logged at debug level not been handled?
If anyone could throw any light on either of these problems, I'd be most grateful.
For the first question, you can change your code to use Logger.clearHandlers to get rid of the additional handler.
Second question: you could add log.setLevel(Level.DEBUG) to get the output you are expecting. As for what setting the level of the handler does, it doesn't seem to control anything. So it is bug; at the very least a documentation bug in their library.
As it turns out, I wasn't using the framework in the expected manner. I've found that the LoggerFactory class is the way that you're supposed to make changes to your loggers. My main method should have been as follows:
override def main( args : Array[String] ) : Unit =
{
val log = Logger.get( "" )
LoggerFactory(
node = "",
level = Some( Level.DEBUG ),
handlers = List( ConsoleHandler( TestFormatter, Some( Level.DEBUG ) ) )
).apply()
log.debug( "DEBUG LOG" )
log.warning( "WARNING LOG" )
}
I'm still not entirely sure why the original code doesn't work, especially since the source of LoggerFactory seems to suggest that it registers the new Handlers by calling addHandler().
However, the output of this main method is:
TEST DEBUG> DEBUG LOG
TEST WARNING> WARNING LOG
which is what I was looking for.

Eclipse IDE doesnt allow me to give the input while running groovy script

I tried to run the groovy script. But unfortunately the script does not ask me for the input and through null pointer exceptions. Please help me what I need to do for this.
static startShell() {
client = new Client()
// TODO add Windows compatibility check
def historyFile = new File(System.getProperty("user.home"), "kitty.history")
historyFile.createNewFile()
def history = new History(historyFile)
def reader = new ConsoleReader()
reader.setBellEnabled(false)
reader.setUseHistory(true)
reader.setDefaultPrompt(PROMPT)
reader.setHistory(history)
reader.addCompletor(new SimpleCompletor(commands as String[]))
LOOP: while (true) {
def input = reader?.readLine().trim()
if (input.length() == 0)
continue
if (["exit", "quit"].contains(input.tokenize().get(0)))
break LOOP
try {
inputHandler(input)
}
catch (Exception e) {
println e.getMessage()
}
I also tried by replacing the reader? with reader also.
Error:
kitty> Caught: java.lang.NullPointerException: Cannot invoke method trim() on null object
at org.apache.kitty.CmdShell.startShell(CmdShell.groovy:100)
at org.apache.kitty.CmdShell.main(CmdShell.groovy:79)
Please Help
I believe this is related to this question:
java.io.Console support in Eclipse IDE
Essentially, Eclipse does not support Console Reader for running applications - though I'm confused as to how Andrew Eisenberg got a working result in Eclipse if that is the case.
Can you simplify your program into something that I can run? I tried something very simple and I was able to have it run both on the command line and inside Eclipse.
Here's the script I created:
import jline.ConsoleReader
def reader = new ConsoleReader()
LOOP: while (true) {
def input = reader?.readLine().trim()
if (input.length() == 0)
continue
if (["exit", "quit"].contains(input.tokenize().get(0)))
break LOOP
println "You said: " + input
}
Can you try running this and see if this works for you?