Closed briangoetz closed 13 years ago
Initial testing shows things working for me, can you email me a full example? I'm probably missing something you're doing.
By the way, note that you can use the shorter "factory + data provider + constructor" approach:
public class A { private Integer m_n;
@Factory(dataProvider = "d") public A(Integer n) { m_n = n; }
public A() {}
@DataProvider public Object[][] d() { return new Object[][] { { new Integer(42) }, { new Integer(43) } }; }
@Test public void a() { System.out.println("a() " + m_n); } }
By the way, note that you can use the shorter "factor + data provider + constructor" approach:
That occurred to me only later. Originally I thought I couldn't do it at all, because I wanted to create a variable multiple @Tests per row emitted by the data provider, but the shorter formulation is attractive enough that I can refactor into that.
Examples attached. package java.util;
import org.testng.annotations.Test;
import java.util.functions.Block;
/**
NullArgsTestHelpers */ public class NullArgsTestHelpers { public static Object[] makeNullArgTests(Fixture fix) { ArrayList
public static class Fixture { public final Block<Object[]> block; public final Object[] args;
public Fixture(Block<Object[]> block, Object... args) {
this.block = block;
this.args = args;
}
}
public static class NonNullArgsTest { private final Fixture fix;
public NonNullArgsTest(Fixture fix) {
this.fix = fix;
}
@Test
public void goodNonNull() {
fix.block.apply(fix.args);
}
}
public static class NullArgsTest { private final Fixture fix; private final int whichArg;
public NullArgsTest(Fixture fix, int whichArg) {
this.fix = fix;
this.whichArg = whichArg;
}
@Test(expectedExceptions = NullPointerException.class)
public void throwWithNull() {
Object[] args = Arrays.copyOf(fix.args, fix.args.length);
args[whichArg] = null;
fix.block.apply(args);
}
} }
package java.util;
import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test;
import java.util.functions.Block; import java.util.functions.Mapper; import java.util.functions.Predicate; import java.util.functions.Reducer;
/**
IteratorsNullTest -- tests of proper null handling in Iterators methods */ public class IteratorsNullTest extends LambdaTestCase {
@Factory(dataProvider = "data") public Object[] makeIteratorsNullTests(NullArgsTestHelpers.Fixture fix) { return NullArgsTestHelpers.makeNullArgTests(fix); }
@DataProvider(name = "data")
public Object[][] makeData() {
List
package java.util;
import java.util.concurrent.ThreadLocalRandom; import java.util.functions.*;
import static org.testng.Assert.assertEquals;
/**
LambdaTestCase
/
public class LambdaTestCase {
protected static Mapper<Integer, Integer> mDoubler = x -> x * 2;
protected static IntMapper
protected ThreadLocalRandom random = ThreadLocalRandom.current();
protected List
protected List
protected List
protected void assertCountSum(Iterable
protected void assertCountSum(Iterator
assertEquals(c, count);
assertEquals(s, sum);
} }
Good to see some closures, but I can't say that I've tested TestNG with Java 8 :-)
I'll try to bring your example down to something I can compile, see if you can do the same, maybe the issue is a Java 8 bug since I'm pretty confident in my data provider tests overall.
Its possible the problem could be java 8 instabilities. But, I found the solution (remove the @Test from the class) by reading this page:
so I don't think it's that.
Here's Block:
public interface Block
/**
* Performs operations upon the provided object which may modify
that object * and/or external state. * @param t an input object / void apply(T t); }
The data provider returns a single Fixture argument per row; a Fixture has a Block<Object[]> and an Object[]. The helper code asserts that the block executes correctly when all the objects are substituted, and then changes each argument to null, one at a time, and asserts that an NPE results. You should be able to replace all the goop in the Fixture constructor with blocks that don't depend on lambdas, eliminate the "extends LambdaTestCase", and make it compile. Here's one that fails for me, without any lambdas:
@Test(groups = { "x" }) public class FooTest {
@Factory(dataProvider = "data")
public Object[] makeIteratorsNullTests(NullArgsTestHelpers.Fixture
fix) { return NullArgsTestHelpers.makeNullArgTests(fix); }
@DataProvider(name = "data")
public Object[][] makeData() {
return new Object[][] {
{ new NullArgsTestHelpers.Fixture(new Block<Object[]>() {
public void apply(Object[] args) {
((String) args[0]).length();
}
}), "foo"
}
};
};
}
On 10/4/2011 3:26 AM, Cedric Beust wrote:
Good to see some closures, but I can't say that I've tested TestNG with Java 8 :-)
I'll try to bring your example down to something I can compile, see if you can do the same, maybe the issue is a Java 8 bug since I'm pretty confident in my data provider tests overall.
I added a @Test at the class level but it's still passing for me so far, here is what I'm using:
@Test public class A { private Integer m_n;
@Factory(dataProvider = "d") public A(Integer n) { m_n = n; }
public A() {}
@DataProvider public Object[][] d() { return new Object[][] { { new Integer(42) }, { new Integer(43) } }; }
public void a() { System.out.println("a() " + m_n); } }
I'll try to expand this to look more like your example.
Does my example above pass for you? If it does, can you expand it to make it break?
I got it down to a single independent file. If I take the @Test off the class, it works. The error I get is:
org.testng.TestNGException:
Method ohNo requires 1 parameters but 0 were supplied in the @Test
annotation.
at org.testng.internal.Parameters.checkParameterTypes(Parameters.java:187)
at org.testng.internal.Parameters.createParameters(Parameters.java:123)
at org.testng.internal.Parameters.createParameters(Parameters.java:357)
at org.testng.internal.Parameters.handleParameters(Parameters.java:434)
at org.testng.internal.FactoryMethod.invoke(FactoryMethod.java:64)
at org.testng.internal.TestNGClassFinder.
Here's the test file:
import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test;
import static org.testng.Assert.assertNotNull;
/**
@Test(groups = { "x" }) public class FooTest {
@Factory(dataProvider = "data")
public Object[] ohNo(String s) {
return makeNullArgTests(s);
}
public static class NullArgsTest {
public final String s;
public NullArgsTest(String s) {
this.s = s;
}
@Test
public void test() {
assertNotNull(s);
}
}
private Object[] makeNullArgTests(String s) {
return new Object[0];
}
@DataProvider(name = "data")
public Object[][] makeData() {
return new Object[][] {
{ "foo" }
};
};
}
On 10/5/2011 2:49 AM, Cedric Beust wrote:
Does my example above pass for you? If it does, can you expand it to make it break?
Thanks for the test case, I just fixed it. Interesting corner case you found :-)
Can you git pull and confirm the fix?
Building now. Might want to update the build instructions on http://testng.org/doc/download.html to include the bit about IVY libs. I did ant -lib . and it worked, but the less ANT-enabled might find themselves stuck (even though it is in README.build.)
Also the ANT file balks when building under a released version of Java 7, had to back off to Java 6.
All worked for me. (Though I had since decided to refactor to use the factory-on-constructor version, mostly because the pattern was more obvious for others to copy from.)
On 10/6/2011 1:35 AM, Cedric Beust wrote:
Thanks for the test case, I just fixed it. Interesting corner case you found :-)
Can you git pull and confirm the fix?
I'm trying to set up a test case which belongs to a group, but whose class body consists of a factory instead of test methods.
The "obvious' thing to do is:
@Test(groups={ "groupName' }) public class Foo { @Factory(dataProvider="d') public Object[] makeInstances(ArgType arg) { ... }
}
But, TestNG complains in a confusing way:
test: [testng] [TestNG] [ERROR] [testng] Method makeInstances requires 1 parameters but 0 were supplied in the @Test annotation. [testng] The tests failed.
Here, it seems to be getting confused that makeInstances() should be a test method, even though it is marked as a factory. I can make the tests run by removing the @Test on the class, but then I can't put the test in a group.
I'm trying to do this all without using an XML file.