My scenario reads a file with hundreds of lines. Each line calls an API Service, but the service may not be running. If I get a non-200 response (available inside the 'Then' method), I want to abandon the Scenario & save time.
How can I tell TechTalk SpecFlow to not carry on with the other tests?
You can use a concept like this .
public static FeatureContext _featureContext;
public binding( FeatureContext featureContext)
{
_featureContext = featureContext;
}
[Given(#"user login")]
public void login(){
// do test
bool testPassed = //set based on test. true or false
binding._featureContext.Current["testPass"] = testPassed;
}
Then in BeforeScenario()
[BeforeScenario(Order = 1)]
public void BeforeScenario()
{
Assert.IsTrue(FeatureContext.Current["testPass"];);
}
I'm trying to test the following class (I've left out the implementation)
public class UTRI implements UTR {
public void runAsUser(String userId, Runnable r);
}
This is the way I would use it:
UTRI.runAsUser("User1", new Runnable () {
private void run() {
//do whatever needs to be done here.
}
});
The problem is, I don't know how to use EasyMock to test functions that return void. That and I'm also not too familiar with testing in general (right out of school!). Can someone help explain to me what I need to do to approach this? I was thinking about making the UTRI a mock and doing expectlastcall after that, but realistically, not sure.
public class UTRITest {
UTRI utri = new UTRI();
#Test
public void testRunAsUser() {
// Create Mocks
Runnable mockRunnable = EasyMock.createMock(Runnable.class);
// Set Expectations
**mockRunnable.run();
EasyMock.expectLastCall().once();**
EasyMock.replay(mockRunnable);
// Call the method under test
utri.runAsUser("RAMBO", **mockRunnable**);
// Verify if run was called on Runnable!!
EasyMock.verify(mockRunnable);
}
}
How to test that the correct exception is thrown when using Cucumber JVM? When using JUnit, I would do something like this:
#Test(expected = NullPointerException.class)
public void testExceptionThrown(){
taskCreater.createTask(null);
}
As you can see, this is very elegant. But how can I achieve the same elegance, when using cucumber JVM? My test looks like this right now:
#Then("the user gets a Null pointer exception$")
public void null_exception_thrown() {
boolean result = false;
try {
taskCreater.createTask(null);
} catch (NullPointerException e) {
result = true;
}
assertTrue(result);
}
Note the need for a try..catch followed by an assertTrue on a flag.
Testing the not-happy-path can be hard. Here's a nice way that I've found to do it with cucumber.
Scenario: Doing something illegal should land you in jail
Then a failure is expected
When you attempt something illegal
And it fails.
OK, don't shoot me because I put the Then before the When, I just think it reads better but you don't have to do that.
I store my excepions in a (cucumber-scoped) world object, but you could also do it in your step file, but this will limit you later.
public class MyWorld {
private boolean expectException;
private List<RuntimeException> exceptions = new ArrayList<>();
public void expectException() {
expectException = true;
}
public void add(RuntimeException e) {
if (!expectException) {
throw e;
}
exceptions.add(e);
}
public List<RuntimeException> getExceptions() {
return exceptions;
}
}
Your steps are then pretty simple:
#Then("a failure is expected")
public void a_failure_is_expected() {
myWorld.expectException();
}
In a step where you are (at least sometimes) expecting an exception, catch it and add it to the world.
#When("you attempt something illegal")
public void you_attempt_something_illegal() {
try {
myService.doSomethingBad();
} catch (RuntimeException e) {
world.add(e);
}
}
Now you can check whether the exception was recorded in the world.
#And("it fails")
public void it_fails() {
assertThat(world.getExceptions(), is(not(empty()));
}
The most valuable thing about this approach is that it won't swallow an exception when you don't expect it.
Have you tried using the junit #Rule annotation with ExpectedException, like this:
#Rule
public ExpectedException expectedEx = ExpectedException.none();
#Then("the user gets a Null pointer exception$")
public void null_exception_thrown() {
expectedEx.expect(NullPointerException.class);
//expectedEx.expectMessage("the message");
taskCreater.createTask(null);
}
Behaviour testing verifies if your project follows specifications, and I doubt the user expects a NullPointerException while using the system.
In my opinion (I'm not familiar with your project), exceptions should only be checked during Unit Tests, as they correspond to an unexpected error or user mistake.
It's very unusual to check for exceptions during behaviour tests. If an exception is thrown during a test, it should fail.
for instance:
test.feature
Given that I have a file "users.txt"
And I try to import users /* If an Exception is thrown here, the test fails */
Then I should see the following users: /* list of users */
In my unit test, I would have:
#Test(expected = MyException.class)
public void importUsersShouldThrowMyExceptionWhenTheFileIsNotFound() {
// mock a call to a file and throw an exception
Mockito.when(reader.readFile("file.txt").thenThrow(new FileNotFoundException());
importer.importUsers();
}
I suggest you to use org.assertj.assertj-core.
Thanks to Assertions class, you could simplify your assertion like bellow:
#Then("the user gets a Null pointer exception$")
public void null_exception_thrown() {
Assertions.assertThatThrownBy(() -> taskCreater.createTask(null)).
isInstanceOf(NullPointerException.class);
}
Never used Cucumber, but would
public void null_exception_thrown() {
try {
taskCreater.createTask(null);
fail("Null Pointer Expected");
} catch (NullPointerException e) {
// Do Nothing
}
}
work for you?
I believe Cucumber is meant to test higher level acceptance tests than lower level unit tests as in that case we will be testing the structure opposed to the behavior which is not the desired usage of the Cucumber framework.
i used to have expected exception name in feature steps. for a calculator test example
Here is my feature file entry for division exception :
Scenario: Dividing a number with ZERO
Given I want to test calculator
When I insert 5.5 and 0.0 for division
Then I got Exception ArithmeticException
So, you may see, I have added the exception name. So, in step definition , i get the name of the exception.
Now, we need to get the exception when dividing by ZERO and put in a variable.
And get this variable to compare its class name(exception name)
so, in step definition where i divide by zero
private Exception actualException;
#When("^I insert (.+) and (.+)for division$")
public void iInsertAndForDivision(double arg0, double arg1) throws Throwable {
try {
result = calculator.div(arg0, arg1);
} catch (Exception e) {
actualException =e;
}
}
And i need the step definition for validating the exception
#Then("^I got Exception (.+)")
public void iGotArithmeticException(String aException) throws Throwable {
Assert.assertEquals("Exception MissMatch",aException,actualException.getClass().getSimpleName());
}
The complete project can be seen here : Steps for cucumber
I need to write the testcase Pass/Fail status in an Excel report. How do I catch the result in a simple way? In Ant XML/HTML reports status (Success/Failed) is displayed so I believe there must be some way to catch this..may be in the #After Class.
Can anyone help me out with this?
I am using Selenium Webdriver with JUnit4 and using Apache POI(oh its screwing my mind too!) for excel handling. Let me know in case you need more info.
Thanks :)
P.S: As I am asking a lot of questions it would be great if someone can change or suggest me changes to make these questions and threads helpful for others.
I got your problem and this is what I have do in all my test cases now -
In your test case if you want to check if 2 Strings are equal -
You might be using this code -
Assert.assertTrue(value1.equals(value2));
And if these values are not equal an AssertionError is generated.
Instead you can change your code like this -
String testCaseStatus = "";
if(value1.equals(value2)){
testCaseStatus = "success";
}
else{
testCaseStatus = "fail";
}
Now you store this result in your excel sheet by passing the testCaseStatus to your code which adds a line to your excel which you have implemented using Apache POI. You can also handle the conditions of "error" if you implement a try catch block.
For example you can catch some exception and add the status as error to your excel sheet.
Edited part of answer -
I just figured out on how to use the TestResult class -
This is some sample code I'm posting -
This is the test case class called ExampleTest -
public class ExampleTest implements junit.framework.Test {
#Before
public void setUp() throws Exception {
}
#After
public void tearDown() throws Exception {
}
#Test
public void test(TestResult result) {
try{
Assert.assertEquals("hari", "");
}catch(AssertionFailedError e){
result.addFailure(this, e);
}catch(AssertionError e){
result.addError(this, e);
}
}
#Override
public int countTestCases() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void run(TestResult result) {
test(result);
}
}
I call the above test case from this code -
public class Test {
public static void main(String[] args) {
TestResult result = new TestResult();
TestSuite suite = new TestSuite();
suite.addTest(new ExampleTest());
suite.run(result);
System.out.println(result.errorCount());
}
}
You can call many test cases by just adding them to this suite and then get the entire result using the TestResult class failures() and errors() methods.
You can read more on this from here.
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).