I recently added a new feature that simplifies the @Factory functionality. As you probably know, a factory is usually a method that returns an array of objects, each of which expected to be an instance of a test class.
You can now save yourself the trouble of creating a method that will return an array of objects and instead, put the @Factory annotation directly on the constructor but with a data provider. Here is an example:
public class FactoryDataProviderSampleTest {
@Factory(dataProvider = "dp")
public FactoryDataProviderSampleTest(int n) {
super(n);
}
@DataProvider
static public Object[][] dp() {
return new Object[][] {
new Object[] { 41 },
new Object[] { 42 },
};
}
}
In the code above, TestNG will create two instances of the class FactoryDataProviderSampleTest, one initialized with "41" and the other with "42".
Thanks to Stephen "Joda" Colebourne for convincing me that this was a worthy addition to TestNG!
> Hi everyone, > I recently added a new feature that simplifies the @Factory functionality. > As you probably know, a factory is usually a method that returns an array of > objects, each of which expected to be an instance of a test class. > You can now save yourself the trouble of creating a method that will return > an array of objects and instead, put the @Factory annotation directly on the > constructor but with a data provider. Here is an example:
> public class FactoryDataProviderSampleTest {
> @Factory(dataProvider = "dp")
> public FactoryDataProviderSampleTest(int n) {
> super(n);
> }
> @DataProvider
> static public Object[][] dp() {
> return new Object[][] {
> new Object[] { 41 },
> new Object[] { 42 },
> };
> }
> }
> In the code above, TestNG will create two instances of the class > FactoryDataProviderSampleTest, one initialized with "41" and the other with > "42". > Thanks to Stephen "Joda" Colebourne for convincing me that this was a worthy > addition to TestNG! > Try it and let me know what you think. > -- > Cédric
> -- > You received this message because you are subscribed to the Google Groups > "testng-users" group. > To post to this group, send email to testng-users@googlegroups.com. > To unsubscribe from this group, send email to > testng-users+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/testng-users?hl=en.
I've been thinking also on a pattern of test I seem to be writing more and more often lately:
@DataProvider(name="something") public Object[][[] provideSomething() { ... ... process a bunch of data - ie csv, jdbc, or other, finding all "failing data"
}
@Test public void fail(SomeObject dataThatFails fail) { fail("Bad data found " + fail);
}
( the test sometimes has some actual tests in it tho )
I've thought of maybe doing this as a @Factory that returns instances of an anonymous inner class at times, but thought something like:
@Test public void testSomeData(IProvidedTest auto) { for (Object each : something ) { auto.callback(new Object[][] { xxx. xxx }; }
}
where IProvidedTest is some form of TestNG generated meta-test, which kinda inverts things. I've not really thought too much on a better way to write it tho.
The other idea I had for tests with a few variations was:
> 2011/4/26 Cédric Beust ♔ <ced...@beust.com>: > > Hi everyone, > > I recently added a new feature that simplifies the @Factory > functionality. > > As you probably know, a factory is usually a method that returns an array > of > > objects, each of which expected to be an instance of a test class. > > You can now save yourself the trouble of creating a method that will > return > > an array of objects and instead, put the @Factory annotation directly on > the > > constructor but with a data provider. Here is an example:
> > public class FactoryDataProviderSampleTest {
> > @Factory(dataProvider = "dp")
> > public FactoryDataProviderSampleTest(int n) {
> > super(n);
> > }
> > @DataProvider
> > static public Object[][] dp() {
> > return new Object[][] {
> > new Object[] { 41 },
> > new Object[] { 42 },
> > };
> > }
> > }
> > In the code above, TestNG will create two instances of the class > > FactoryDataProviderSampleTest, one initialized with "41" and the other > with > > "42". > > Thanks to Stephen "Joda" Colebourne for convincing me that this was a > worthy > > addition to TestNG! > > Try it and let me know what you think. > > -- > > Cédric
> > -- > > You received this message because you are subscribed to the Google Groups > > "testng-users" group. > > To post to this group, send email to testng-users@googlegroups.com. > > To unsubscribe from this group, send email to > > testng-users+unsubscribe@googlegroups.com. > > For more options, visit this group at > > http://groups.google.com/group/testng-users?hl=en.
> -- > You received this message because you are subscribed to the Google Groups > "testng-users" group. > To post to this group, send email to testng-users@googlegroups.com. > To unsubscribe from this group, send email to > testng-users+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/testng-users?hl=en.
On Wed, Apr 27, 2011 at 1:04 AM, Mark Derricutt <m...@talios.com> wrote: > Nice indeed.
> I've been thinking also on a pattern of test I seem to be writing more and > more often lately:
> @DataProvider(name="something") > public Object[][[] provideSomething() { > ... > ... process a bunch of data - ie csv, jdbc, or other, finding all "failing > data"
> }
> @Test > public void fail(SomeObject dataThatFails fail) { > fail("Bad data found " + fail); > }
Invoking a test method that will always fail? Not sure what the point of that would be(?).
> ( the test sometimes has some actual tests in it tho )
> I've thought of maybe doing this as a @Factory that returns instances of an > anonymous inner class at times, but thought something like:
> @Test > public void testSomeData(IProvidedTest auto) { > for (Object each : something ) { > auto.callback(new Object[][] { xxx. xxx }; > } > }
> where IProvidedTest is some form of TestNG generated meta-test, which > kinda inverts things. I've not really thought too much on a better way to > write it tho.
That seems intriguing but I can't think of a use case, can you?
> The other idea I had for tests with a few variations was:
I've often heard that :) It's also maybe a sign my ideas are crazy, and warrant being shot down. Either that or I've just not explained myself clearly enough - quite likely the former tho.
> Invoking a test method that will always fail? Not sure what the point of > that would be(?).
One scenario where I've done this is as part of our integration test suite. First the setup - the integration test starts an embedded ApacheDS LDAP server, along with an embedded Apache Felix OSGi container and our RESTful application. This runs thru a series of fairly standard tests doing HTTP calls with content checking return types, LDAP validations etc. etc.
As part of our internal auditing we store in the database a record of all HTTP calls to the API, and I have a "test" which attempts to give us a form of resource coverage in the form of DataProvider that first queries the server for available REST resources, then queries the request audit log, and finds any resource/http-method combinations that were not called during the test run.
That DataProvider then feeds those "missing requests" to the test method which records a test failure for any resource that was not tested.
Another scenario I have for this is also at the tail end of our integration tests in which a data provider scans the generated webserver log over the course of the integration test, pulling out any stacktrace and passing that over to a test to record an "unhandled exception" in the server.
For these I could use the DataProvider/Test approach or a Factory. The DataProvider/Test approach seems to work (mentally to me) better in that theres only ever a single test involved.
One of the scenario's I've thought of but haven't yet implemented is more a "system health test", where a Factory/DataProvider inspects the database for bad data and reports a test failure in each case ( eg. Customer X has a country of Australia but has billing details for New Zealand Dollars ).
>> The other idea I had for tests with a few variations was:
> This would be very limited since Java annotations can only contain > constants...
True - but I've done things similar to this in the past where I could only provide String values/constants. In the case of Strings, parameters would be checked via reflection for having a valueOf(String) method ( String, Integer, Double, Float, etc. have these ).
The current flow has a static factory method returning the test object instances itself, and the more I think about it, I think a variation of the Factory setup could for all these scenarios. Basically have a new IFactoryGenerator interface with a #yield(Object) method on it, if an @Factory method returns void, and takes IFactoryGenerator as an argument then do something like:
I've been trying to come up with a way to use this feature together with parameters(from the xml) and I've come up with this little hack:
boolean single; @Parameters({"single"}) public DemoTest(@Optional("true") boolean single) { this.single = single; } @Factory(dataProvider = "createInstances") public DemoTest(String name) { .... } @DataProvider public Object[][] createInstances() { if(single) { return new Object[][] { new Object[] { "single" } }; } return new Object[][] { new Object[] { "first" }, new Object[] { "second" }, }; }
The first constructor will only be called to create a temporary object to call the non-static DataProvider.
The second one will be the one actually used. It would be nice if there was a better way to do something like this, but this works good so far.
Hint: This way you can run only one instance using rightclick->test file and test all instances when using the xml file (when building for example). -- View this message in context: http://old.nabble.com/New-feature%3A-simpler-factories-tp31474374p315... Sent from the testng-users mailing list archive at Nabble.com.
On Thu, May 5, 2011 at 6:43 AM, Santo Pfingsten <s...@tetralog.de> wrote: > I've been trying to come up with a way to use this feature together with > parameters(from the xml) and I've come up with this little hack:
> boolean single; > @Parameters({"single"}) > public DemoTest(@Optional("true") boolean single) { > this.single = single; > } > @Factory(dataProvider = "createInstances") > public DemoTest(String name) { > .... > } > @DataProvider > public Object[][] createInstances() { > if(single) { > return new Object[][] { new Object[] { "single" } }; > } > return new Object[][] { > new Object[] { "first" }, > new Object[] { "second" }, > }; > }
> The first constructor will only be called to create a temporary object to > call the non-static DataProvider. > The second one will be the one actually used. It would be nice if there was > a better way to do something like this, but this works good so far.
> -- > You received this message because you are subscribed to the Google Groups > "testng-users" group. > To post to this group, send email to testng-users@googlegroups.com. > To unsubscribe from this group, send email to > testng-users+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/testng-users?hl=en.