public class Main {
public static void main(String[] args) throws IOException, URISyntaxException, TransformerException {
TransformerFactory factory = TransformerFactory.newInstance();
Source xslt = new StreamSource(new File("transform.xslt"));
Transformer transformer = factory.newTransformer(xslt);
Source text = new StreamSource(new File("input.xml"));
transformer.transform(text, new StreamResult(new File("output.xml")));
}
}
The first step in writing JUnit tests is knowing what you want to test. So that is the best place to start. First, look at your code and try to break down which are the moving pieces. Ask yourself "what could possibly break? what am I worried about not working?" For instance, you could test what happens if transform.xslt doesn't exist.
I think step one for you is to take all of the code you currently have in main() and move it into an object. You can start by making it an instance method on the class. That will give you a way to decouple the code you want to test from running main.
If you search online you will find many tutorials on JUnit, it will likely help you to work through a few of them.
Related
unable to serialize DoFnWithExecutionInformation{doFn=com.orderly.dataflow.RosterFileReader#60ec7684, mainOutputTag=Tag, sideInputMapping={}, schemaInformation=DoFnSchemaInformation{elementConverters=[]}}
java.lang.IllegalArgumentException: unable to serialize DoFnWithExecutionInformation{doFn=com.orderly.dataflow.RosterFileReader#60ec7684, mainOutputTag=Tag, sideInputMapping={}, schemaInformation=DoFnSchemaInformation{elementConverters=[]}}
I am not sure this is possible. I understand in apache beam, these functions must be serializable for scaling out but during test time I also want to mock where we read from.
Is there some kind of context or something I can create to inject the interface which is mockable for reading?
Here is my code
public class RosterFileReader extends DoFn<String, PractitionerStandardOutputDto> {
private static final Logger log = LoggerFactory.getLogger(RosterFileReader.class);
private final String projectId;
private GCPBucketStorage storage;
public RosterFileReader(String projectId, GCPBucketStorage storage) {
I am wondering if there is a context I can send in? GCPBucketStorage.java is OUR API since googles was not that mockable. In this way, we have full control of throwing exceptions and testing recovery as well as other scenarios.
EDIT: I would be willing to settle for some code like this
if(isRunningLocally) {
storage = new MockStorage();
} else {
storage = new GCPBucketStorageImpl();
}
it basically kind of sucks having test code like that in production code, but this END to END test has already caught bugs!!!!!! bugs that are missed in the unit testing that people are doing. We generally do not do single class or unit testing and only do what twitter calls Feature Testing since it allows huge refactors without touching tests -> https://blog.twitter.com/engineering/en_us/topics/insights/2017/the-testing-renaissance.html
I can reach into the Mock using static fields I guess(Again, I hate doing that but this test is so valuable having it end to end truly)
EDIT 2: Is serialization a ton like hadoop where you have to define classes to deploy along with the main jar? Perhaps I just need a document to make GCPStorage and GCPBucketStorageImpl serializable (and MockStorage as well most likely since it is in production code :( ) -> The if..else is totally worth it on the integration bugs we are finding pre-CI so people don't break the code on master ever.
EDIT 3:
This looks very promising -> https://gist.github.com/jlewi/f1cd323dc88bd58601ef
Will update post after trying.
thanks,
Dean
Actually, just making the interface serializable seems to work in test (not tested in production yet) Along with this last line in the production code that is ugly(and I wonder if I can inject this instead) ->
yup, pretty ugly to have test code in production :(. Of BIG worth note is instead of injecting the interface, I inject GCPBucketStorageImpl.java (our prod implemntation) and now pass in the mock(which subclasses the prod class <---- This is done so we get test validation on someone modifying production class to not being serializable in which case we would not catch the issue.
I'm trying to test my verticle but with mocked MongoDB (not to perform real DB actions during the process of unit testing), I've tried to mock my client, but looks like when I use vertx.deployVerticle() my mocks are not being taken into account.
Here's an example of my test setup:
#RunWith(VertxUnitRunner.class)
#PrepareForTest({ MongoClient.class })
public class VerticleTest {
#Rule
public PowerMockRule rule = new PowerMockRule();
private Vertx vertx;
private Integer port;
#Before
public void setUp(TestContext context) throws Exception {
vertx = Vertx.vertx();
mockStatic(MongoClient.class);
MongoClient mongo = Mockito.mock(MongoClientImpl.class);
when(MongoClient.createShared(any(), any())).thenReturn(mongo);
ServerSocket socket = new ServerSocket(0);
port = socket.getLocalPort();
socket.close();
DeploymentOptions options = new DeploymentOptions().setConfig(new JsonObject().put("http.port", port));
vertx.deployVerticle(TalWebVerticle.class.getName(), options, context.asyncAssertSuccess());
}
And what I actually see, that is that MongoClient.createShared is still being called, though I've mocked it.
What can I do in this case?
Edit 1.
Looks like the problem is that MongoClient is an interface and PowerMockito is not able to mock static methods in this case.
I'm still trying to find workaround for this case.
I didn't know that the MongoClient is an interface then I gave my first answer.
PowerMock doesn't supports mocking static calls interfaces (bug #510, Javaassist fixed exception, but mocking static methods still isn't supported). It will be called in next release.
I was focusing on issue in PowerMock, not why it's needed. I agree with answer which was provided in Mailing List.
You could work around it by creating a helper method in your own code
that returns MongoClient.createdShared(). Then in your test, mock that
helper to return your mocked MongoClientImp
But it will be not a work around, but right design solution. Mocking MongoClient is not a good approach, because you should not mock types you don't own.
So better way will be create a custom helper which will create MongoClientfor you and then mock this the helper in unit test. Also you will need integration tests for this helper which will call real MongoClient.createdShared().
If you don't have an opportunity to change code (or you don't want to change code without tests), then I've create an example with work around how PowerMock bug could be bypassed.
Main ideas:
create a custom MainMockTransformer. The transformer will transform interfaces classes to enable supporting mock static calls for interfaces
create a custom PowerMockRunner which will be used to add the custom MockTransformer to transformers chains.
Please, bring to notice on packages name where these new classes are located. It's important. If you want to move them into another packages then you will need to add these new packages to #PowerMockIgnore.
I am new to Nunit and Moq
I have a static class like this:
public static class StaticClass1
{
public static void Prepare()
{
//some logic
}
}
public static class StaticClass2
{
public static void Initialize(some_parameter)
{
//some logic
if (some_condition(some_parameter))
{
StaticClass1.Prepare();
}
}
}
I need to test the function AccountService.Initialize() in which I need to verify StaticClass1.Prepare() is being called at least once
I think that to answer this question I would say something like "You need to get experience in how to layer a project".
When unit testing a method you want to unit test that single method, and mock the dependencies, exactly as you try to do if I understand you correctly. Now it's not optimal to call static public methods from one class to another static method in another class since it makes it difficult to isolate you unit tests and what they should test (you end up with testing two completely different methods in the same unit test instead of separating the code and unit tests).
On another approach you break the D in SOLID (Dependency inversion principle) that you can read more about here -> https://en.wikipedia.org/wiki/SOLID_(object-oriented_design). You want to depend upon abstractions rather than concrete classes.
Lastly I thought that I would be a bit selfish and share a link to an article series that I have written myself. It's about Test Driven Development and uses Moq as unit testing tool and focuses on how to think when layering and unit testing a complete project (in a small scale). I'm absolute certain that it will help you understand on how to continue with you own projects and code.
It's based upon 4 articles. The first in the series is here -> http://www.andreasjohansson.eu/technical-blog/getting-started-unit-testing-a-web-project-part-1-introduction-and-setting-up-the-project/
Hope it helps!
I've started a few WebDriver projects in Eclipse Juno but i'm not satisfied with my structure, i think is to stupid and not efficient at all.
Beneath you can see my project three now. The TEST_xxx.java files are functions to trigger the files in the test package.
Here is an example of one function in a TEST_xxx.java file:
public void a_search_product_by_sku(String sku) throws InterruptedException {
System.out.println("Running Testsuite 3 - Navigation - Testcase 1 - Search product by SKU");
tests.navigation nav = new tests.navigation(BASE_URL, driver);
nav.search_product_by_sku(sku);
}
This calls the function search_product_by_sku() that is inside the navigation class inside the test package. This function look like this:
public void search_product_by_sku(String sku) throws InterruptedException {
driver.get(url + "/k/k.aspx");
driver.findElement(By.id("q")).clear();
driver.findElement(By.id("q")).sendKeys(sku);
driver.findElement(By.cssSelector("input.submit")).click();
boolean status = driver.findElement(By.cssSelector("BODY")).getText().matches("^[\\s\\S]*Status:[\\s\\S]*$");
Assert.assertEquals(true, status);
}
All this seems too hard to maintain, and since I'm not a very experienced programmer I'm really out of ideas and i hoped that someone here could help me.
Thanks in advance!
First a class name should start with a capital letter.
date should be Date.
Instead of having four classes in tests package. You can merge the 4 classes into a single class.
And the classes, and the testing classes would be good if they are in the same package.
I'm new to the test automation scene so forgive me if this is a stupid question but google has failed me this time. Or at least anything I've read has just confused me further.
I'm using JUnit 4 and Selenium Webdriver within Eclipse. I have several tests that I need to run as a suite and also individually. At the moment these tests run fine when run on their own. At the start of the test an input box is presented to the tester/user asking first what server they wish to test on (this is a string variable which becomes part of a URL) and what browser they wish to test against. At the moment when running the tests in a suite the user is asked this at the beginning of each test, because obviously this is coded into each of their #Before methods.
How do I take in these values once, and pass them to each of the test methods?
So if server = "server1" and browser = "firefox" then firefox is the browser I want selenium to use and the URL I want it to open is http://server1.blah.com/ for all of the following test methods. The reason I've been using seperate #Before methods is because the required URL is slightly different for each test method. i.e each method tests a different page, such as server1.blah.com/something and server1.blah.com/somethingElse
The tests run fine, I just don't want to keep inputting the values because the number of test methods will eventually be quiet large.
I could also convert my tests to testNG if there is an easier way of doing this in testNG. I thought the #BeforeSuite annotation might work but now I'm not sure.
Any suggestions and criticism (the constructive kind) are much appreciated
You can adapt the solution for setting a global variable for a suite in this answer to JUnit 4 Test invocation.
Basically, you extend Suite to create MySuite. This creates a static variable/method which is accessible from your tests. Then, in your tests, you check the value of this variable. If it's set, you use the value. If not, then you get it. This allows you to run a single test and a suite of tests, but you'll only ask the user once.
So, your suite will look like:
public class MySuite extends Suite {
public static String url;
/**
* Called reflectively on classes annotated with <code>#RunWith(Suite.class)</code>
*
* #param klass the root class
* #param builder builds runners for classes in the suite
* #throws InitializationError
*/
public MySuite(Class<?> klass, RunnerBuilder builder) throws InitializationError {
this(builder, klass, getAnnotatedClasses(klass));
// put your global setup here
MySuite.url = getUrlFromUser();
}
}
This would be used in your Suite like so:
#RunWith(MySuite.class)
#SuiteClasses({FooTest.class, BarTest.class, BazTest.class});
Then, in your test classes, you can either do something in the #Before/#After, or better look at TestRule, or if you want Before and After behaviour, look at ExternalResource. ExternalResource looks like this:
public static class FooTest {
private String url;
#Rule
public ExternalResource resource= new ExternalResource() {
#Override
protected void before() throws Throwable {
url = (MySuite.url != null) ? MySuite.url : getUrlFromUser();
};
#Override
protected void after() {
// if necessary
};
};
#Test
public void testFoo() {
// something which uses resource.url
}
}
You can of course externalize the ExternalResource class, and use it from multiple Test Cases.
I think the main functionality of TestNG that will be useful here is not just #BeforeSuite but #DataProviders, which make it trivial to run the same test with a different set of values (and won't require you to use statics, which always become a liability down the road).
You might also be interested in TestNG's scripting support, which makes it trivial to ask the user for some input before the tests start, here is an example of what you can do with BeanShell.
It might make sense to group tests so that the test suite will have the same #Before method code, so you have a test suite for each separate.
Another option might be to use the same base url for each test but navigate to the specific page by getting selenium to click through to where you want to carry out the test.
If using #RunWith(Suite.class), you can add static methods with #BeforeClass (and #AfterClass), which will run before (and after) the entire Suite you define. See this question.
This of course won't help if you are referring to the entire set of classes found dynamically, and are not using Suite runner.