I have the following tryout code:
[TestMethod]
public void VisibilitySucces()
{
testPage.HideParagraph();
testPage.ShowParagraph();
}
[TestMethod, ExpectedException(typeof(WebDriverTimeoutException))]
public void ShouldBeVisibleException()
{
testPage.ShouldBeVisibleException();
}
[TestCleanup]
public void TestCleanup()
{
switch (TestContext.CurrentTestOutcome)
{
case UnitTestOutcome.Passed:
Console.WriteLine("Passed!");
break;
default:
Console.WriteLine("The test outcome is " + TestContext.CurrentTestOutcome.ToString());
break;
}
Browser.Quit();
}
Now, the first test has the outcome Passed as expected.
The second test does throw the exception (I've tested it without the ExpectedException attribute). It's marked as passed visually, but the outcome in the console is showing InProgress.
How can this be when this status is queried in the TestCleanup?
Related
I have implemented an event listener for Cucumber events:
public class AdccEventListener implements ConcurrentEventListener {
private static boolean stepFailed = false;
#Override
public void setEventPublisher(EventPublisher publisher) {
System.out.println("register handlers!!!");
publisher.registerHandlerFor(TestCaseStarted.class, this::scenarioStartedHandler);
publisher.registerHandlerFor(TestCaseFinished.class, this::scenarioFinishedHandler);
publisher.registerHandlerFor(TestStepStarted.class, this::stepStartedHandler);
publisher.registerHandlerFor(TestStepFinished.class, this::stepFinishedHandler);
}
private void scenarioStartedHandler(TestCaseStarted event) {
stepFailed = false;
}
private void scenarioFinishedHandler(TestCaseFinished event) {
BaseTestUtils.reportInfoMessage("Scenario finish name is: " + event.getTestCase().getName() + " end of Scenario statement!");
if (stepFailed) {
Result result = event.getResult();
setPrivateField(result, "status", Status.FAILED);
}
}
private void stepStartedHandler(TestStepStarted event) {
if (event.getTestStep() instanceof PickleStepTestStep) {
PickleStepTestStep testStep = (PickleStepTestStep) event.getTestStep();
BaseTestUtils.reportInfoMessage("step name is: " + testStep.getStep().getText() + " end of statement!");
ThreadLocalEvent.setStep(testStep);
}
}
private void stepFinishedHandler(TestStepFinished event) {
if (event.getTestStep() instanceof PickleStepTestStep) {
PickleStepTestStep testStep = (PickleStepTestStep) event.getTestStep();
Result result = event.getResult();
ThreadLocalEvent.setResult(result);
if (result.getStatus().equals(Status.FAILED)) {
if (!testStep.getStep().getKeyWord().startsWith("Given")) {
stepFailed = true;
setPrivateField(result, "status", Status.PASSED);
}
}
}
}
private void setPrivateField(Object subject, String fieldName, Object value) {
try {
Field f = subject.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
f.set(subject, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
i have declared the Event Listener as a plugin in the CucumberOptions of the RunTests class.
#CucumberOptions(plugin = {"pretty", "html:target/cucumber", "json:target/cucumber.json", "com.radware.bdd.AdccEventListener"},
glue = {"com.radware.tests"},
features = {"src/test/resources/Features"},
strict = true,
tags = {"#Functional"})
Now when i am executing tests on my local work station all is good. i am getting all events that were published in listener.
But, When the same project is executed on the docker container, listener does not get any events.
f. e. start Step, end Step events.
any idea what could cause it to not work under container?
Thank you.
Stas
I have found a problem.
When Maven tests were initiated from Jenkins or Docker container CucumberOptions arguments were passed. one of arguments was "--plugin". so my local definitions were overwritten.
Resolution is to add my custom plugin "com.radware.bdd.AdccEventListener" to the options passed through cli command.
I have created a JUNIT test cases for elasticsearch CRUD operation i have given the code below. After code reviewing phase i got an update from team that i have covered all the positive scenario of test cases still not yet covered the negative scenarios. I am not aware of handling the negative use cases.
#Test
void findById() throws Exception {
EmployeeInformation EmployeeGet = Eservice.findById("elcrud", "2");
assertNotNull(EmployeeGet.getId());
assertNotNull(EmployeeGet.getFirstName());
assertNotNull(EmployeeGet.getLastName());
}
#Test
void deleteProfileDocument() throws Exception {
String Result = Eservice.deleteProfileDocument("elcrud", "3");
System.out.println(Result);
assertEquals(Result, "DELETED");
}
#Test
void search() throws Exception {
List<EmployeeInformation> Emp=Eservice.searchByTechnology("Lucidworks","elcrud");
System.out.println(Emp.size());
int Result = Emp.size();
assertTrue(Result >= 0 );
}
#Test
void searchByName() throws Exception {
List<EmployeeInformation> Emp=Eservice.findProfileByName("junit","elcrud");
System.out.println(Emp.size());
int Result = Emp.size();
assertTrue(Result >= 0 );
}
Could some one help me to implement the negative scenario of JUNIT test cases for above code?
I think you tech team wants a test if the operation of ES failed, give no results or any other unexpected scenario happens.
One example could be the deletion of a profile document:
You already covered the test if the delete operation is successful. But you dont have a test if this operation failed or is not handled successful.
#Test
void deleteProfileDocument() throws Exception {
//here you delete a profile which is NOT in the index
String Result = Eservice.deleteProfileDocument("elcrud", "3");
System.out.println(Result);
//and here you asssert the negative result. (Not sure which result will come)
assertEquals(Result, "NOT_FOUND");
}
I also see that on your test you throw an exception in case of an error. This could be another good negative test scenario. So, if you can send an operation to ES and this operation throws an exception you can create a test to expect this exception.
For Junit4 you could use the following:
#Test(expected = YourExpectedException.class)
For Junit5 you could use this:
Exception exception = assertThrows(YourExpectedException.class, () -> {
Eservice.findProfileByName(Exception values);
});
String expectedMessage = "expected message";
String actualMessage = exception.getMessage();
assertTrue(actualMessage.contains(expectedMessage));
EDit by addtional questions
If you have a positive and a negeative test, I would suggest to keep them in separate test methods. So there will be no need to comment things out and in.
In your case it could be like:
positve:
#Test
void testUpdateItem_POSITIVE() throws Exception {
....
}
negative:
#Test
void testUpdateItem_NEGATIVE() throws Exception {
....
}
#Test(expected = NotFound.class)
void shouldThrowExceptionWhenProfileIsNotExist() throws Exception {
Eservice.findById("elcrud", "some_id");
}
Instead NotFound place your exception which is thrown when search profile with an id which is not exist
A field of MongoDB Entity MyCardDO, explicitly set it to unique
#Indexed(unique=true)
private String uid;
and there is a MyCardService to crud MyCardDO, and there is a MyCardServiceTest to test MyCardService, there is a add_repeat_uid_record_failed inner MyCardServiceTest to test the uid cannot be duplicated,
MyCardDO myCardDO1 = new MyCardDO();
myCardDO1.setUid("1");
myCardService.add(myCardDO1);
try {
MyCardDO myCardDO2 = new MyCardDO();
myCardDO2.setUid("1");
myCardService.add(myCardDO2);
Assert.fail();
} catch (DuplicateKeyException e) {
assertTrue(e.getMessage().contains("E11000 duplicate key error collection: opportunity-test.pro_mycard index: uid dup key: { : \"1\" }"));
}
If I run this test method directly it's OK, but I run the whole MyCardServiceTest this method is failed, and from Wireshark I know the createIndexes only executed once, if dropped the collection it will not createIndexes again
#After
public void tearDown() {
mongoTemplate.dropCollection(MyCardDO.class);
}
So how to let spring to execute createIndexes before every test method? that is
#Before
public void setUp() {
// how to auto execute createIndexes before every test method
// prepare some test data
myCardService.add(myCardDO1);
}
p.s.
#RunWith(SpringRunner.class)
#DataMongoTest(includeFilters = #ComponentScan.Filter(type= FilterType.ASSIGNABLE_TYPE,value={MyCardService.class}))
#ActiveProfiles("test")
#Import(SpringMongoConfig.class)
public class MyCardServiceTest {
//...
}
Wireshark screenshot
Final my resolution :
#After
public void tearDown() {
mongoTemplate.remove(new Query(), MyCardDO.class);
}
#AfterClass
public static void finalClean() {
mongoTemplate.dropCollection(MyCardDO.class);
}
that is after finished every test method only delete all records and at final when the whole test class is finished to drop the collection.
Below is an Example.
public class MyController : Controller
{
[Route("~/api/mycontroller")]
[HttpGet]
public int ID()
{
try
{
return somecontroller.getID(ID);
}
catch (Exception ex)
{
throw ex;
}
}
}
Above it the controller that is fetching the ID from the below controller.
Below is the controller that it is inherited.
public class Controller : ApiController
{
public int ID
{
get
{
return int.Parse(HttpContext.Current.Request.Headers["ID"]);
}
}
}
How do i write unit test case for the following.???
Oh, unit testing HttpContext.Current. That's one of my favorites :-)
You can't write a unit test for something that depends on HttpContext.Current. So if you want to write testable code the first step is to search in your entire solution for the HttpContext.Current keyword and simply wipe them out from existence.
In this particular case you would of course replace them with the corresponding abstraction:
public class Controller : ApiController
{
public int ID
{
get
{
return int.Parse(Request.Headers.GetValues("ID").FirstOrDefault());
}
}
}
Now it's completely trivial to unit test your Web API controller properly:
// arrange
var sut = new MyController();
sut.Request = new HttpRequestMessage();
sut.Request.Headers.TryAddWithoutValidation("ID", "5");
// act
var actual = sut.SomeControllerAction();
// assert
Assert.AreEqual(5, actual);
I'm using VS2010 Premium, Coded UI Tests.
Do you know how to re-execute failed test cases after run?
If test was passed after re-execution then it should be passed in result report.
Not so optimal way but you could put all your code to try/catch block and rerun the test if an exception is thrown:
[CodedUITest]
public class CodedUITest
{
private static int _maxTestRuns = 5;
[TestCleanup]
public void Cleanup()
{
//If the test has reached the max number of executions then it is failed.
if (_maxTestRuns == 0)
Assert.Fail("Test executed {0} times and it was failed", _maxTestRuns);
}
[TestMethod]
public void CodedUITestMethod()
{
try
{
this.UIMap.RecordedMethod1();
}
catch (Exception exception)
{
//Call Cleanup, rerun the test and report the error.
if (_maxTestRuns > 0)
{
_maxTestRuns--;
TestContext.WriteLine(exception.Message);
TestContext.WriteLine("Running Again...");
this.Cleaup();
this.CodedUITestMethod();
}
}
}
}
You could also generalize the method Schaliasos proposes, we could create a base class like this:
[CodedUITest]
public class _TestBase
{
private static int _maxTestRuns;
public Exception _currentException;
public _TestBase()
{
}
public void TryThreeTimes(Action testActions)
{
_maxTestRuns = 3;
_currentException = null;
while (_maxTestRuns > 0)
{
try
{
testActions();
}
catch (Exception exception)
{
_maxTestRuns--;
_currentException = exception;
}
if (_currentException == null)
break; // Test passed, stop retrying
}
if (_maxTestRuns == 0) // If test failed three times, bubble up the exception.
{
throw _currentException;
}
}
/// <summary>
///Gets or sets the test context which provides
///information about and functionality for the current test run.
///</summary>
public TestContext context
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
private TestContext testContextInstance;
}
And then when we write tests we could inherit the class above and do this:
[CodedUITest]
public class NewTestClass : _TestBase
{
[TestMethod]
public void MyTestMethod1()
{
TryThreeTimes(new Action(() =>
// Assertions and Records come here
Assert.IsTrue(false);
}));
}
[TestMethod]
public void MyTestMethod2()
{
TryThreeTimes(new Action(() =>
// Assertions and Records come here.
Assert.IsTrue(true);
}));
}
}
I have been thinking about how this could be made even simpler, any suggestions would be appreciated. This at least saves quite a bit of code if you have many tests that you would like to run often, maybe it would make sense for some to generalize the function TryThreeTimes so one of the arguments would be the number of reruns.