Revision: 602
http://svn.sourceforge.net/jwebunit/?rev=602&view=rev
Author: henryju
Date: 2006-11-08 07:04:53 -0800 (Wed, 08 Nov 2006)
Log Message:
-----------
Fix cookie support, especially manually adding cookie to the test context.
Add related test cases.
Modified Paths:
--------------
branches/1.x/jwebunit-commons-tests/src/main/java/net/sourceforge/jwebunit/tests/TestContextTest.java
branches/1.x/jwebunit-commons-tests/src/main/java/net/sourceforge/jwebunit/tests/WebCookieTest.java
branches/1.x/jwebunit-commons-tests/src/main/resources/testcases/WEB-INF/web.xml
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/IJWebUnitDialog.java
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/TestContext.java
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/TestingEngineRegistry.java
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/WebTester.java
branches/1.x/jwebunit-htmlunit-plugin/src/main/java/net/sourceforge/jwebunit/htmlunit/HtmlUnitDialog.java
branches/1.x/src/changes/changes.xml
Added Paths:
-----------
branches/1.x/jwebunit-commons-tests/src/main/java/net/sourceforge/jwebunit/tests/util/CookiesServlet.java
Modified:
branches/1.x/jwebunit-commons-tests/src/main/java/net/sourceforge/jwebunit/tests/TestContextTest.java
===================================================================
---
branches/1.x/jwebunit-commons-tests/src/main/java/net/sourceforge/jwebunit/tests/TestContextTest.java
2006-11-08 15:00:49 UTC (rev 601)
+++
branches/1.x/jwebunit-commons-tests/src/main/java/net/sourceforge/jwebunit/tests/TestContextTest.java
2006-11-08 15:04:53 UTC (rev 602)
@@ -22,7 +22,7 @@
super.setUp();
context = new TestContext();
context.setAuthorization("user", "pwd");
- context.addCookie("key", "val");
+ context.addCookie("key", "val", "www.foo.bar");
context.setLocale(Locale.CANADA_FRENCH);
}
@@ -36,6 +36,7 @@
Cookie c = (Cookie)cookies.get(0);
assertEquals(c.getName(), "key");
assertEquals(c.getValue(), "val");
+ assertEquals(c.getDomain(), "www.foo.bar");
assertEquals(Locale.CANADA_FRENCH, context.getLocale());
assertEquals("http://localhost:8080", context.getBaseUrl());
assertNull(context.getResourceBundleName());
Modified:
branches/1.x/jwebunit-commons-tests/src/main/java/net/sourceforge/jwebunit/tests/WebCookieTest.java
===================================================================
---
branches/1.x/jwebunit-commons-tests/src/main/java/net/sourceforge/jwebunit/tests/WebCookieTest.java
2006-11-08 15:00:49 UTC (rev 601)
+++
branches/1.x/jwebunit-commons-tests/src/main/java/net/sourceforge/jwebunit/tests/WebCookieTest.java
2006-11-08 15:04:53 UTC (rev 602)
@@ -9,10 +9,9 @@
import net.sourceforge.jwebunit.tests.util.JettySetup;
/**
- * Test the Cookies provided by WebTestCase using the PseudoServer test package
- * provided by Russell Gold in httpunit.
+ * Test the Cookies methods provided by WebTestCase.
*
- * @author Vivek Venugopalan
+ * @author Julien HENRY
*/
public class WebCookieTest extends JWebUnitAPITestCase {
@@ -23,12 +22,34 @@
public void setUp() throws Exception {
super.setUp();
- getTestContext().addCookie("cookie1", "Cookievalue1");
- getTestContext().setBaseUrl(HOST_PATH +
"/ExpectedTableAssertionsTest");
- beginAt("/TableAssertionsTestPageHtml.html");
+ getTestContext().addCookie("cookie1", "Cookievalue1",
"localhost");
+ getTestContext().setBaseUrl(HOST_PATH);
}
- public void testAssertCookieDump() throws Throwable {
- //dumpCookies();
+ public void testAddCookie() {
+ beginAt("/cookies.jsp");
+ assertTextPresent("cookie1=Cookievalue1");
+ }
+
+ public void testAddAnotherCookie() {
+ getTestContext().addCookie("cookie2", "Cookievalue2", "localhost");
+ beginAt("/cookies.jsp");
+ assertTextPresent("cookie1=Cookievalue1");
+ assertTextPresent("cookie2=Cookievalue2");
+ }
+
+ public void testAssertCookiePresent() throws Throwable {
+ beginAt("/cookies.jsp");
+ assertCookiePresent("serveurCookie");
}
+
+ public void testAssertCookieValue() throws Throwable {
+ beginAt("/cookies.jsp");
+ assertCookieValueEquals("serveurCookie", "foo");
+ }
+
+ public void testAssertCookieMatch() throws Throwable {
+ beginAt("/cookies.jsp");
+ assertCookieValueMatch("serveurCookie", "fo*");
+ }
}
\ No newline at end of file
Added:
branches/1.x/jwebunit-commons-tests/src/main/java/net/sourceforge/jwebunit/tests/util/CookiesServlet.java
===================================================================
---
branches/1.x/jwebunit-commons-tests/src/main/java/net/sourceforge/jwebunit/tests/util/CookiesServlet.java
(rev 0)
+++
branches/1.x/jwebunit-commons-tests/src/main/java/net/sourceforge/jwebunit/tests/util/CookiesServlet.java
2006-11-08 15:04:53 UTC (rev 602)
@@ -0,0 +1,67 @@
+/******************************************************************************
+ * jWebUnit project (http://jwebunit.sourceforge.net) *
+ * Distributed open-source, see full license under LICENCE.txt *
+
******************************************************************************/
+package net.sourceforge.jwebunit.tests.util;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+
+public class CookiesServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ protected void doGet(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException,
IOException {
+ doPost(request, response);
+ }
+
+ protected void doPost(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException,
IOException {
+ response.setContentType("text/html");
+ PrintWriter out = response.getWriter();
+ out.write(HtmlHelper.getStart("Submitted cookies"));
+ out.write("<h1>Submitted cookies</h1>\n<p>Cookies are:");
+ /*
+ * Prints POST and GET cookies as name=value1[,value2...]
separated with
+ * <br/>
+ */
+
+ Cookie[] cookies = request.getCookies();
+ if (cookies != null) {
+ for (int i = 0; i < cookies.length; i++) {
+ out.write(cookies[i].getName() + "=" +
cookies[i].getValue()
+ + "<br/>");
+ }
+ }
+
+ out.write(" </p>\n");
+ String ref = request.getHeader("Referer");
+ if (ref == null) {
+ if (request.getParameterValues("myReferer") != null) {
+ ref =
request.getParameterValues("myReferer")[0];
+ }
+ }
+ out.write(HtmlHelper.getLinkParagraph("return", ref));
+
+ out.write(HtmlHelper.getEnd());
+
+ Cookie cookie = new Cookie("serveurCookie","foo");
+ response.addCookie(cookie);
+ }
+
+}
Modified:
branches/1.x/jwebunit-commons-tests/src/main/resources/testcases/WEB-INF/web.xml
===================================================================
---
branches/1.x/jwebunit-commons-tests/src/main/resources/testcases/WEB-INF/web.xml
2006-11-08 15:00:49 UTC (rev 601)
+++
branches/1.x/jwebunit-commons-tests/src/main/resources/testcases/WEB-INF/web.xml
2006-11-08 15:04:53 UTC (rev 602)
@@ -8,10 +8,18 @@
<servlet-name>ParamsServlet</servlet-name>
<servlet-class>net.sourceforge.jwebunit.tests.util.ParamsServlet</servlet-class>
</servlet>
+<servlet>
+ <servlet-name>CookiesServlet</servlet-name>
+
<servlet-class>net.sourceforge.jwebunit.tests.util.CookiesServlet</servlet-class>
+</servlet>
<servlet-mapping>
<servlet-name>ParamsServlet</servlet-name>
<url-pattern>/params.jsp</url-pattern>
</servlet-mapping>
+<servlet-mapping>
+ <servlet-name>CookiesServlet</servlet-name>
+ <url-pattern>/cookies.jsp</url-pattern>
+</servlet-mapping>
<security-constraint>
<web-resource-collection>
Modified:
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/IJWebUnitDialog.java
===================================================================
---
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/IJWebUnitDialog.java
2006-11-08 15:00:49 UTC (rev 601)
+++
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/IJWebUnitDialog.java
2006-11-08 15:04:53 UTC (rev 602)
@@ -4,7 +4,8 @@
******************************************************************************/
package net.sourceforge.jwebunit;
-import net.sourceforge.jwebunit.exception.ElementNotFoundException;
+import java.util.List;
+
import net.sourceforge.jwebunit.exception.ExpectedJavascriptAlertException;
import net.sourceforge.jwebunit.exception.ExpectedJavascriptConfirmException;
import net.sourceforge.jwebunit.exception.ExpectedJavascriptPromptException;
@@ -50,34 +51,13 @@
void setScriptingEnabled(boolean value);
/**
- * Test if a cookie is present with given name.
+ * Get all cookies.
*
- * @param cookieName
- * name of the cookie.
- * @return true if the cookie is present.
+ * @return List of javax.servlet.http.Cookie.
*/
- boolean hasCookie(String cookieName);
+ List getCookies();
/**
- * Get cookie value.
- *
- * @param cookieName
- * name of the cookie.
- * @return value of the cookie.
- */
- String getCookieValue(String cookieName);
-
- /**
- * Get all cookies name and value.
- *
- * @param cookieName
- * name of the cookie.
- * @return array with 2 columns. First is cookie names, second is cookie
- * values.
- */
- String[][] getCookies();
-
- /**
* Test if the window with the given name is present.
*
* @param windowName
Modified:
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/TestContext.java
===================================================================
---
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/TestContext.java
2006-11-08 15:00:49 UTC (rev 601)
+++
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/TestContext.java
2006-11-08 15:04:53 UTC (rev 602)
@@ -93,18 +93,34 @@
/**
* Add a cookie to the test context. These cookies are set on the
- * WebConversation when an [EMAIL PROTECTED] HttpUnitDialog}is begun.
+ * conversation when you use a {WebTester#beginAt}.
*
* @param name
* cookie name.
* @param value
* cookie value.
+ * @param domain
+ * cookie domain (ie localhost or www.foo.bar).
*/
- public void addCookie(String name, String value) {
- cookies.add(new Cookie(name, value));
+ public void addCookie(String name, String value, String domain) {
+ Cookie c = new Cookie(name, value);
+ c.setDomain(domain);
+ c.setPath(""); //If we don't do this, cookie is not send to the
server.
+ cookies.add(c);
}
/**
+ * Add a cookie to the test context. These cookies are set on the
+ * conversation when you use a {WebTester#beginAt}.
+ *
+ * @param cookie
+ * a cookie.
+ */
+ public void addCookie(Cookie cookie) {
+ cookies.add(cookie);
+ }
+
+ /**
* Return true if a basic authentication has been set on the context via
* [EMAIL PROTECTED] #setAuthorization}.
*/
Modified:
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/TestingEngineRegistry.java
===================================================================
---
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/TestingEngineRegistry.java
2006-11-08 15:00:49 UTC (rev 601)
+++
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/TestingEngineRegistry.java
2006-11-08 15:04:53 UTC (rev 602)
@@ -27,19 +27,22 @@
/**
* Gets the map of testing engines defined within jwebunit.
- *
+ * Need to be synchronized for concurrent testing.
* @return
*/
- public static Hashtable getTestingEngineMap() {
+ public static synchronized Hashtable getTestingEngineMap() {
if (testingEngineMap == null) {
testingEngineMap = new Hashtable();
+ String cp = "net.sourceforge.jwebunit.htmlunit.HtmlUnitDialog";
+ //Try to load HtmlUnitDialog to check if it is present.
try {
- String cp = "net.sourceforge.jwebunit.htmlunit.HtmlUnitDialog";
Class.forName(cp);
- testingEngineMap.put(TESTING_ENGINE_HTMLUNIT, cp);
} catch (ClassNotFoundException e) {
- //Nothing to do
+ // HtmlUnitDialog is not present in the classpath. Return an
empty map.
+ return testingEngineMap;
}
+ // HtmlUnitDialog was found. Add it to the map.
+ testingEngineMap.put(TESTING_ENGINE_HTMLUNIT, cp);
}
return testingEngineMap;
}
Modified:
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/WebTester.java
===================================================================
---
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/WebTester.java
2006-11-08 15:00:49 UTC (rev 601)
+++
branches/1.x/jwebunit-core/src/main/java/net/sourceforge/jwebunit/WebTester.java
2006-11-08 15:04:53 UTC (rev 602)
@@ -5,9 +5,13 @@
package net.sourceforge.jwebunit;
import java.io.PrintStream;
+import java.util.Iterator;
+import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
+import javax.servlet.http.Cookie;
+
import junit.framework.Assert;
import junit.framework.AssertionFailedError;
import net.sourceforge.jwebunit.exception.ElementNotFoundException;
@@ -1663,23 +1667,50 @@
}
/**
- * Checks to see if a cookie is present in the response. Contributed by
- * Vivek Venugopalan.
+ * Checks to see if a cookie is present in the response.
*
* @param cookieName
* The cookie name
*/
public void assertCookiePresent(String cookieName) {
- Assert.assertTrue("Could not find Cookie : [" + cookieName +
"]",
- getDialog().hasCookie(cookieName));
+ List cookies = getDialog().getCookies();
+ for (Iterator i = cookies.iterator(); i.hasNext();) {
+ if (((Cookie) i.next()).getName().equals(cookieName)) {
+ return;
+ }
+ }
+ Assert.fail("Could not find Cookie with name [" + cookieName +
"]");
}
+ /**
+ * Check to see if a cookie has the given value.
+ *
+ * @param cookieName
+ * The cookie name
+ * @param expectedValue
+ * The cookie value
+ */
public void assertCookieValueEquals(String cookieName, String
expectedValue) {
assertCookiePresent(cookieName);
- Assert.assertEquals(expectedValue, getDialog().getCookieValue(
- cookieName));
+ List cookies = getDialog().getCookies();
+ for (Iterator i = cookies.iterator(); i.hasNext();) {
+ Cookie c = (Cookie) i.next();
+ if (c.getName().equals(cookieName)) {
+ Assert.assertEquals(expectedValue,
c.getValue());
+ return;
+ }
+ }
+ Assert.fail("Should not be reached");
}
+ /**
+ * Check to see if a cookie value match the given regexp.
+ *
+ * @param cookieName
+ * The cookie name
+ * @param regexp
+ * The regexp
+ */
public void assertCookieValueMatch(String cookieName, String regexp) {
assertCookiePresent(cookieName);
RE re = null;
@@ -1688,9 +1719,17 @@
} catch (RESyntaxException e) {
Assert.fail(e.toString());
}
- Assert.assertTrue("Unable to match [" + regexp + "] in cookie
\""
- + cookieName + "\"",
re.match(getDialog().getCookieValue(
- cookieName)));
+ List cookies = getDialog().getCookies();
+ for (Iterator i = cookies.iterator(); i.hasNext();) {
+ Cookie c = (Cookie) i.next();
+ if (c.getName().equals(cookieName)) {
+ Assert.assertTrue("Unable to match [" + regexp
+ + "] in cookie \"" + cookieName
+ "\"", re.match(c
+ .getValue()));
+ return;
+ }
+ }
+ Assert.fail("Should not be reached");
}
// Form interaction methods
@@ -2109,11 +2148,13 @@
}
public void dumpCookies() {
- String[][] cookies = getDialog().getCookies();
- for (int i = 0; i < cookies.length; i++) {
- System.out.println(cookies[i][0] + "=" + cookies[i][1]);
+ List cookies = getDialog().getCookies();
+ for (Iterator i = cookies.iterator(); i.hasNext();) {
+ Cookie c = (Cookie) i.next();
+ System.out.println("Name="+c.getName() + "; Value=" +
c.getValue() + "; Domain="
+ + c.getDomain() + "; Comment=" +
c.getComment() + "; MaxAge="
+ + c.getMaxAge() + "; Path=" +
c.getPath() + "; Version=" + c.getVersion());
}
-
}
// Debug methods
@@ -2229,18 +2270,18 @@
* Exemple: <br/>
*
* <pre>
- * <FORM
action="http://my_host/doit" method="post">
- * <P>
- * <SELECT multiple size="4"
name="component-select">
- * <OPTION selected
value="Component_1_a">Component_1</OPTION>
- * <OPTION selected
value="Component_1_b">Component_2</OPTION>
- * <OPTION>Component_3</OPTION>
- * <OPTION>Component_4</OPTION>
- * <OPTION>Component_5</OPTION>
- * </SELECT>
- * <INPUT type="submit"
value="Send"><INPUT type="reset">
- * </P>
- * </FORM>
+ * <FORM
action="http://my_host/doit" method="post">
+ * <P>
+ * <SELECT multiple
size="4" name="component-select">
+ * <OPTION selected
value="Component_1_a">Component_1</OPTION>
+ * <OPTION selected
value="Component_1_b">Component_2</OPTION>
+ *
<OPTION>Component_3</OPTION>
+ *
<OPTION>Component_4</OPTION>
+ *
<OPTION>Component_5</OPTION>
+ * </SELECT>
+ * <INPUT type="submit"
value="Send"><INPUT type="reset">
+ * </P>
+ * </FORM>
* </pre>
*
* Should return [Component_1, Component_2, Component_3, Component_4,
Modified:
branches/1.x/jwebunit-htmlunit-plugin/src/main/java/net/sourceforge/jwebunit/htmlunit/HtmlUnitDialog.java
===================================================================
---
branches/1.x/jwebunit-htmlunit-plugin/src/main/java/net/sourceforge/jwebunit/htmlunit/HtmlUnitDialog.java
2006-11-08 15:00:49 UTC (rev 601)
+++
branches/1.x/jwebunit-htmlunit-plugin/src/main/java/net/sourceforge/jwebunit/htmlunit/HtmlUnitDialog.java
2006-11-08 15:04:53 UTC (rev 602)
@@ -16,6 +16,8 @@
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -163,7 +165,9 @@
}
}
- public void closeBrowser() throws ExpectedJavascriptAlertException,
ExpectedJavascriptConfirmException, ExpectedJavascriptPromptException {
+ public void closeBrowser() throws ExpectedJavascriptAlertException,
+ ExpectedJavascriptConfirmException,
+ ExpectedJavascriptPromptException {
wc = null;
if (this.expectedJavascriptAlerts.size() > 0) {
throw new ExpectedJavascriptAlertException(
@@ -181,8 +185,6 @@
.getMessage());
}
-
-
}
public void gotoPage(String initialURL)
@@ -214,40 +216,29 @@
}
}
- /**
- * @see
net.sourceforge.jwebunit.IJWebUnitDialog#hasCookie(java.lang.String)
- */
- public boolean hasCookie(String cookieName) {
+ public List getCookies() {
+ List result = new LinkedList();
final HttpState stateForUrl = wc.getWebConnection().getState();
Cookie[] cookies = stateForUrl.getCookies();
for (int i = 0; i < cookies.length; i++) {
- if (cookies[i].getName().equals(cookieName))
- return true;
+ javax.servlet.http.Cookie c = new
javax.servlet.http.Cookie(
+ cookies[i].getName(),
cookies[i].getValue());
+ c.setComment(cookies[i].getComment());
+ c.setDomain(cookies[i].getDomain());
+ Date expire = cookies[i].getExpiryDate();
+ if (expire == null) {
+ c.setMaxAge(-1);
+ } else {
+ Date now = Calendar.getInstance().getTime();
+ //Convert milli-second to second
+ Long second = new
Long((expire.getTime()-now.getTime())/1000);
+ c.setMaxAge(second.intValue());
+ }
+ c.setPath(cookies[i].getPath());
+ c.setSecure(cookies[i].getSecure());
+ c.setVersion(cookies[i].getVersion());
+ result.add(c);
}
- return false;
- }
-
- /**
- * @see
net.sourceforge.jwebunit.IJWebUnitDialog#getCookieValue(java.lang.String)
- */
- public String getCookieValue(String cookieName) {
- final HttpState stateForUrl = wc.getWebConnection().getState();
- Cookie[] cookies = stateForUrl.getCookies();
- for (int i = 0; i < cookies.length; i++) {
- if (cookies[i].getName().equals(cookieName))
- return cookies[i].getValue();
- }
- throw new RuntimeException("Cookie " + cookieName + " not
found");
- }
-
- public String[][] getCookies() {
- final HttpState stateForUrl = wc.getWebConnection().getState();
- Cookie[] cookies = stateForUrl.getCookies();
- String[][] result = new String[cookies.length][2];
- for (int i = 0; i < cookies.length; i++) {
- result[i][0] = cookies[i].getName();
- result[i][1] = cookies[i].getValue();
- }
return result;
}
@@ -642,6 +633,14 @@
}
}
});
+ // Deal with cookies
+ for (Iterator i = getTestContext().getCookies().iterator();
i.hasNext();) {
+ javax.servlet.http.Cookie c =
(javax.servlet.http.Cookie) i.next();
+ wc.getWebConnection().getState().addCookie(
+ new Cookie(c.getDomain() != null ?
c.getDomain() : "", c
+ .getName(),
c.getValue(), c.getPath(), c
+ .getMaxAge(),
c.getSecure()));
+ }
}
/**
Modified: branches/1.x/src/changes/changes.xml
===================================================================
--- branches/1.x/src/changes/changes.xml 2006-11-08 15:00:49 UTC (rev
601)
+++ branches/1.x/src/changes/changes.xml 2006-11-08 15:04:53 UTC (rev
602)
@@ -8,6 +8,10 @@
</properties>
<body>
<release version="1.4" date="UNKNOW">
+ <action type="fix" dev="Julien Henry">
+ Fix cookie support. You can now properly manually add cookie
to the conversation by
+ using TestContext.addCookie() before calling beginAt().
+ </action>
<action type="add" dev="Julien Henry">
Add setExpectedJavascript[Alert/Confirm/Prompt] methods to
check presence of
Javascript message boxes.
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Jwebunit-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jwebunit-development