I am having a test suite which is having the following structure
TestClass1
- testmethod1()
- testmethod2()
- testmethod3()
- testmethod4()
TestClass2
- testmethod11()
- testmethod22()
- testmethod33()
- testmethod44()
In the above structure i want to execute the testmethod4() as the final one. ie) executed at last.
There is a annotation #FixMethodOrder which executes a method in order not the testclass. Is there any mechanism to maintain order in test class and testmethod together. With the #FixMethodOrder i can execute the method by renaming the name of the test method but i can't instruct junit to execute the test class as the final one(last one).
Though quoting #Andy again -
You shouldn't care about test ordering. If it's important, you've got
interdependencies between tests, so you're testing behaviour +
interdependencies, not simply behaviour. Your tests should work
identically when executed in any order.
But if the need be to do so, you can try out Suite
#RunWith(Suite.class)
#Suite.SuiteClasses({
TestClass2.class,
TestClass1.class
})
public class JunitSuiteTest {
}
where you can either specify
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestClass1 {
#AfterClass
public void testMethod4() {
and then take care to name your method testMethod4 as such to be executed at the end OR you can also use #AfterClass which could soon be replaced by #AfterAll in Junit5.
Do take a look at Controlling the Order of the JUnit test by Alan Harder
#shiriam as #Andy Turner already pointed out, the order of your tests shouldn't come in question when running the tests.
If you have a routine that you want executed before doing any tests, you could use a static block of code in one of the classes.
Think of something like this:
class TestBootstrap {
// singleton instance
private static final instance;
private boolean initialized;
private TestBootstrap(){
this.initialized = false;
}
public static TestBootstrap getInstance(){
if (instance == null){
instance = new TestBootstrap()
}
}
public void init(){
// make the method idempotent
if (!initialzed){
// do init stuff
initialized = true;
}
}
public boolean isInitialized(){
return initialized;
}
}
Then in your tests use something like this:
class TestClass1{
#BeforeClass
public void setup(){
TestBootstrap.getInstance().init();
}
#Test
public void testmethod1(){
// assertions
}
// ....
}
class TestClass2{
#BeforeClass
public void setup(){
TestBootstrap.getInstance().init();
}
#Test
public void testmethod11(){
// assertions
}
// ...
}
By using the singleton instance for doing the setup for the tests you ensure that you perform the initialization of your test environment only once, independently of the order in which the test classes are executed.
Related
I need your help to understand a unit (method) behaviors within a unit test class shown below.
public void updateAccount(Account account) {
if (!accountExists(account.getAccountNo())) {
throw new AccountNotFoundException();
}
accounts.put(account.getAccountNo(), account);
}
The method shown above tells me that the exception will be thrown if the account is not found
However the 2nd test ( updateNotExistedAccount) method shown below shows that it's expected that the method above (updateAccount ) should throw an exception to past the test. However, newAccount is already initialized /created within the createNewAccount so it exists already. So I assume that the updateNotExistedAccount will failed the test (because updateAccount won't throw exceptions in that case ), however updateNotExistedAccount passed.
public class InMemoryAccountDaoTests {
private static final String NEW_ACCOUNT_NO = "998";
private Account newAccount;
private InMemoryAccountDao accountDao;
#Before
public void init() {
newAccount = new Account(NEW_ACCOUNT_NO, 200);
accountDao = new InMemoryAccountDao();
}
#Test
public void createNewAccount() {
accountDao.createAccount(newAccount);
assertEquals(accountDao.findAccount(NEW_ACCOUNT_NO), newAccount); }
#Test(expected = AccountNotFoundException.class)
public void updateNotExistedAccount() { accountDao.updateAccount(newAccount);
}
Is it wrong if I assume updateNotExistedAccount will fail the test?
Seems like the data are persisted from one test to another.
Try to clean the data after each test.
#After
public void clean(){
// this method will be run after each single #Test method
// you can use this to clean all resoruces after a test. in your case for example
accountDao.deleteById(newAccount.getId());
}
For your test to be complete, and to test the update, I would do something like this:
#Test
public void updateExistingAccount() {
accountDao.createAccount(newAccount);
dbAccount = accountDao.findAccount(newAccount.getId);
dbAccount.setName("");
dbAccount.setSurname("");
// etc...
accountDao.updateAccount(dbAccount);
dbAccountUpdated = accountDao.findAccount(newAccount.getId);
assertEquals(accountDao.findAccount(dbAccountUpdated.getId()), dbAccount);
}
UPDATE
Consider also that #Before and #After runs respectively before and after each single test.
#BeforeClass and #AfterClass respectively before and after all tests.
With the use of these 4 methods you can start always the test with the desired dataset, and after the test clean everything as it were.
Please see:
Difference between #Before, #BeforeClass, #BeforeEach and #BeforeAll
To properly check need to look at your newAccount code as well as what all you are Mocking.
Check your #Before method as that will run before every #Test
Check if which test is running first when you run your suite
I would like to test the following method with JUnit:
private static boolean systemIsWindows() {
String os = System.getProperty("os.name").toLowerCase();
return os.startsWith("win");
}
Frankly, the only thing I've come up with is to basically copy to same logic to the test. This would, of course, protect against the method being inadvertently broken, but sounds somehow counter-intuitive.
What would be a better way to test this method?
In your Unit tests, you can change the value of the property:
System.setProperty("os.name", "Linux")
After that, you can then test/call your systemIsWindows() method to check that what it returns using asserts.
To make it easier to set a System property and to unset that property on completion of the test (thereby facilitating test isolation, self containment) you could use either of the following JUnit add-ons:
JUnit4: JUnit System Rules
JUnit5: JUnit Extensions
For example:
#Test
#SystemProperty(name = "os.name", value = "Windows")
public void aTest() {
assertThat(systemIsWindows(), is(true));
}
#Test
#SystemProperty(name = "os.name", value = "MacOs")
public void aTest() {
assertThat(systemIsWindows(), is(false));
}
A much better way in JUnit 5 is to use #EnabledOnOs https://junit.org/junit5/docs/5.2.0/api/org/junit/jupiter/api/condition/EnabledOnOs.html
So for example:
#Test
#EnabledOnOs({OS.WINDOWS})
public void aTest() {
assertThat(systemIsWindows(), is(false));
}
My specific question is with regards to JUnit's Parameterized Tests, filtering (essentially not running) tests if it contains a certain property. For example:
#Test
public void test1() {
if (property.contains("example")) {
return;
}
assertEquals(expected, methodToTest1(actual));
}
#Test
public void test2() {
if (property.contains("example")) {
return;
}
assertEquals(expected, methodToTest2(actual));
}
The question is, does a technique exist where the constraint if (property.equals("example"))... be defined somewhere else statically, instead of before each and every test method? Like this:
/** define constraint "property.equals("example")" somewhere **/
#Test
public void test1() {
assertEquals(expected, methodToTest1(actual));
}
#Test
public void test2() {
assertEquals(expected, methodToTest2(actual));
}
You may use JUnit's Assume feature together with #Before.
Add an #Before method to your test class
#Before
public void dontRunIfExample() {
assumeFalse(property.contains("example"));
}
and remove the if block from each of your tests.
It depends on how you are running your JUnit tests. You can quite literally use Java's System.getProperty("conditionForTest"). Then if you are launching them by command line you will need to specify them with -DconditionForTest=true or if you are running the tests with ant then it can be passed into the an target.
<sysproperty key="conditionForTest" value="true"/>
I would like to provide elegant mechanism to skip chosen tests when value of some environmental variable is not admissible. I chose adding my own annotation #RunCondition to define which value are allowed for particular tests. Then I created my own listener for TestNG that marks tests as disabled when value of environmental variable is not within admissible scope defined in annotation parameters.
My code looks as follows:
public class ExampleTest {
private int envVar;
#BeforeClass
public void setUp() {
//set up of some environmental variables which depends on external source
StaticContext.setVar(getValueFromOuterSpace());
}
#RunCondition(envVar=2)
#Test
public void testFoo(){
}
}
public class SkipTestTransformer implements IAnnotationTransformer {
#Override
public void transform(ITestAnnotation iTestAnnotation, Class aClass, Constructor constructor, Method method) {
RunCondition annotation = method.getAnnotation(RunCondition.class);
int[] admissibleValues = annotation.envVar();
for (int val : admissibleValues) {
if (StaticContext.getVar() == val) {
return; // if environmental variable matches one of admissible values then do not skip
}
}
iTestAnnotation.setEnabled(false);
}
}
public #interface RunCondition {
int[] envVar();
}
My code works great, but there is a small problem that transform method is invoked before the setUp which is the #BeforeClass function. Is there any other possibility to run Transformer after all initialization of test? I consider such solution elegant and clear and I don't want any ugly if clauses to reach my goal...
I'm using Java 7 and TestNG v5.11.
Try to implement IMethodInterceptor (An instance of this class will be invoked right before TestNG starts invoking test methods.) instead of annotation transformer. It will allow to manage list of tests which will be executed. It also allows to work with your tests annotations. The restriction is that test methods having dependencies will not be passed to intercept method.
There is a better concept directly supported by the testing frameworks called assumptions. You should not disable the test, but rather skip the execution:
in JUnit you can use assumeThat(boolean) family of methods
in TestNG you can throw SkipException
In that case the method will not disappear, it will be marked as skipped.
You can check your own annotation in a setup method (#BeforeMethod) and throw a SkipException to skip this test.
public class ExampleTest {
private int envVar;
#BeforeClass
public void setUp() {
//set up of some environmental variables which depends on external source
StaticContext.setVar(2);
}
#BeforeMethod
public void checkRunCondition(Method method) {
RunCondition annotation = method.getAnnotation(RunCondition.class);
if (annotation != null) {
int[] admissibleValues = annotation.envVar();
for (int val : admissibleValues) {
if (StaticContext.getVar() == val) {
// if environmental variable matches one of admissible values then do not skip
throw new SkipException("skip because of RunCondition");
}
}
}
}
#RunCondition(envVar = 2)
#Test
public void testFoo() {
}
#Retention(RetentionPolicy.RUNTIME)
public #interface RunCondition {
int[] envVar();
}
}
I just discovered when creating some CRUD tests that you can't set data in one test and have it read in another test (data is set back to its initialization between each test).
All I'm trying to do is (C)reate an object with one test, and (R)ead it with the next. Does JUnit have a way to do this, or is it ideologically coded such that tests are not allowed to depend on each other?
Well, for unit tests your aim should be to test the smallest isolated piece of code, usually method by method.
So testCreate() is a test case and testRead() is another. However, there is nothing that stops you from creating a testCreateAndRead() to test the two functions together. But then if the test fails, which code unit does the test fail at? You don't know. Those kind of tests are more like integration test, which should be treated differently.
If you really want to do it, you can create a static class variable to store the object created by testCreate(), then use it in testRead().
As I have no idea what version of Junit you talking about, I just pick up the ancient one Junit 3.8:
Utterly ugly but works:
public class Test extends TestCase{
static String stuff;
public void testCreate(){
stuff = "abc";
}
public void testRead(){
assertEquals(stuff, "abc");
}
}
JUnit promotes independent tests. One option would be to put the two logical tests into one #Test method.
TestNG was partly created to allow these kinds of dependencies among tests. It enforces local declarations of test dependencies -- it runs tests in a valid order, and does not run tests that depend on a failed test. See http://testng.org/doc/documentation-main.html#dependent-methods for examples.
JUnit is independent test. But, If you have no ways, you can use "static" instance to store it.
static String storage;
#Test
public void method1() {
storage = "Hello"
}
#Test
public void method2() {
Assert.assertThat(something, is(storage));
}
How much processing time do these tests take? If not a lot, then why sweat it. Sure you will create some object unnecessarily, but how much does this cost you?
#Test
void testCreateObject() {
Object obj = unit.createObject();
}
#Test
void testReadObject() {
Object obj = null;
try {
obj = unit.createObject(); // this duplicates tests aleady done
} catch (Exception cause) {
assumeNoException(cause);
}
unit.readObject(obj);
}
in this basic example, the variable is changed in the test A, and can be used in the test B
public class BasicTest extends ActivityInstrumentationTestCase2 {
public BasicTest() throws ClassNotFoundException {
super(TARGET_PACKAGE_ID, launcherActivityClass);
}
public static class MyClass {
public static String myvar = null;
public void set(String s) {
myvar = s;
}
public String get() {
return myvar;
}
}
private MyClass sharedVar;
#Override
protected void setUp() throws Exception {
sharedVar = new MyClass();
}
public void test_A() {
Log.d(S,"run A");
sharedVar.set("blah");
}
public void test_B() {
Log.d(S,"run B");
Log.i(S,"sharedVar is: " + sharedVar.get());
}
}
output result is:
run A
run B
sharedVar is: blah