#{extends '../main.html'/}# #{set title:'Webpieces QuickStart'/}# #{set tab:'management'/}# #{renderTagArgs 'docHome.html'/}# #{renderTagArgs 'quickStartList.html'/}#
First, if you haven't read the twitter blog Feature Testing, we highly suggest reading that! There are 4 types of testing with Webpieces
In all modes, we typically use an in-memory database to be able to test out writing with production code and then reading back with production code preventing integration issues that get missed when you test them in isolation. We also have this all setup for you unless you are going to use noSQL in which case you will need to setup your own in-memory version of a noSQL database which is typically just a Map of Map of Maps and very easy to setup. In the case of cassandra, like so
BOOOM!!!! In-memory cassandra which we coded that on one project very quickly though you do need to use a SortedMap on the last map since columns are in-order!!! I need to revive PlayOrmand rename it as well to some sort of noSQL mapping layer name that is much like hibernate but scalable and more KISS keeping many features of hibernate out on purpose to keep ou complexity which keeps out bugs more.
This is a great mode in that with a little swapping of things via guice bindings, we put your http client directly on top of the webserver router and templating engine. This means you can step directly from test into the platform bypassing the socket layer unlike Feature Testing Remote Client mode which goes over a socket.
We give you a great cheat in that you can copy TestLesson2Html.java so copy this file and edit it to remove all the tests and remote endpoints. TestLesson2Html demonstrates how to swap out remote clients deep within your code with mocks to create a feature test with mock remote systems. Here is our copied and modified file TestHelloWorld.java:
*[package org.webpieces.helloworld;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.junit.Before;
import org.junit.Test;
import org.webpieces.ddl.api.JdbcApi;
import org.webpieces.ddl.api.JdbcConstants;
import org.webpieces.ddl.api.JdbcFactory;
import org.webpieces.httpclient11.api.HttpFullRequest;
import org.webpieces.httpclient11.api.HttpFullResponse;
import org.webpieces.httpclient11.api.HttpSocket;
import org.webpieces.httpparser.api.common.Header;
import org.webpieces.httpparser.api.common.KnownHeaderName;
import org.webpieces.httpparser.api.dto.HttpRequest;
import org.webpieces.httpparser.api.dto.HttpRequestLine;
import org.webpieces.httpparser.api.dto.HttpUri;
import org.webpieces.httpparser.api.dto.KnownHttpMethod;
import org.webpieces.httpparser.api.dto.KnownStatusCode;
import org.webpieces.plugins.hibernate.HibernatePlugin;
import org.webpieces.webserver.test.AbstractWebpiecesTest;
import org.webpieces.webserver.test.ResponseExtract;
import org.webpieces.webserver.test.ResponseWrapper;
public class TestHelloWorld extends AbstractWebpiecesTest {
private JdbcApi jdbc = JdbcFactory.create(JdbcConstants.jdbcUrl, JdbcConstants.jdbcUser, JdbcConstants.jdbcPassword);
private HttpSocket http11Socket;
private static String pUnit = HibernatePlugin.PERSISTENCE_TEST_UNIT;
@Before
public void setUp() throws InterruptedException, ClassNotFoundException, ExecutionException, TimeoutException {
//clear in-memory database
jdbc.dropAllTablesFromDatabase();
Server webserver = new Server(getOverrides(false), null, new ServerConfig(pUnit, JavaCache.getCacheLocation()));
webserver.start();
http11Socket = connectHttp(false, webserver.getUnderlyingHttpChannel().getLocalAddress());
}
@Test
public void testDynamicHelloWorld() {
HttpFullRequest req = createRequest("/helloworld/deano/555");
CompletableFuture respFuture = http11Socket.send(req);
ResponseWrapper response = ResponseExtract.waitResponseAndWrap(respFuture);
response.assertStatusCode(KnownStatusCode.HTTP_200_OK);
response.assertContains("Hello deano. Your id is 555");
}
public static HttpFullRequest createRequest(String uri) {
HttpRequestLine requestLine = new HttpRequestLine();
requestLine.setMethod(KnownHttpMethod.GET);
requestLine.setUri(new HttpUri(uri));
HttpRequest req = new HttpRequest();
req.setRequestLine(requestLine );
req.addHeader(new Header(KnownHeaderName.HOST, "yourdomain.com"));
HttpFullRequest fullReq = new HttpFullRequest(req, null);
return fullReq;
}
}]*
The setup is quite simple, drop all tables, then create the production server with some certain platform overrides(this is where we swap stuff for testing). We then call webserver.start and then create a simulated socket(it looks like a socket but isn't and sits on top of the webserver directly). The setup is very simple.
Next in the test, we simply create an http request object for a GET request to "/helloworld/deano/555" and then send it, get the response and verify it is 200 OK and that the html contains what we expected
You ready to be blow completely away!!! Just modify the setup method changing both locations of 'false' into isRemoteClientMode and add boolean isRemoteClientMode = true; like so:
*[@Before
public void setUp() throws InterruptedException, ClassNotFoundException, ExecutionException, TimeoutException {
//clear in-memory database
jdbc.dropAllTablesFromDatabase();
boolean isRemoteClientMode = true;
Server webserver = new Server(getOverrides(isRemoteClientMode), null, new ServerConfig(pUnit, JavaCache.getCacheLocation()));
webserver.start();
http11Socket = connectHttp(isRemoteClientMode, webserver.getUnderlyingHttpChannel().getLocalAddress());
}]*
Under the covers, we bind to port 0 picking up the available port and then query for the http and https ports so we can connect the client to the same port allowing you to run many of these test in parallel even since they connect to different ports.
Selenium can be a double edged sword but can work really really well in some cases. There is already an example in TestLesson5WithSelenium.java where you can see how we get the ports the webserver bound to and feed those into the urls for selenium to test properly
You may even be able to get selenium tests to run in parallel if it can open different windows for testing since we can run our webserver on multiple ports at the same time as well
Ok, we do advise against this type of testing as it will limit your refactoring and keeping your design up to date. We fine the more unit testing there is, the more people are afraid to refactor because they have to rewrite the test suite meaning "THERE WILL BE BUGS" they introduce. The other form of testing doesn't necessarily catch everything but it catches way more in our experience.
Next Custom Tags