Skip to content

Commit

Permalink
Extracted code snippets from the unittest docs and added travis config.
Browse files Browse the repository at this point in the history
  • Loading branch information
Takashi Matsuo committed Mar 27, 2015
1 parent 20e5204 commit 5a6e56a
Show file tree
Hide file tree
Showing 16 changed files with 648 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
language: java

env:
- TEST_DIR=unittests

script: cd $TEST_DIR && mvn test
5 changes: 5 additions & 0 deletions unittests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# appengine-ndb-snippets

## unittests

This subdirectory contains code snippets for [Local Unit Testing for Java](https://cloud.google.com/appengine/docs/java/tools/localunittesting).
140 changes: 140 additions & 0 deletions unittests/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>

<groupId>com.google.appengine.samples.unittest</groupId>
<artifactId>unittests</artifactId>

<properties>
<appengine.app.version>1</appengine.app.version>
<appengine.version>1.9.18</appengine.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<prerequisites>
<maven>3.1.0</maven>
</prerequisites>

<dependencies>
<!-- Compile/runtime dependencies -->
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-1.0-sdk</artifactId>
<version>${appengine.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>

<!-- Test Dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-testing</artifactId>
<version>${appengine.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-stubs</artifactId>
<version>${appengine.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<!-- for hot reload of the web application-->
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>display-dependency-updates</goal>
<goal>display-plugin-updates</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<version>3.1</version>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<archiveClasses>true</archiveClasses>
<webResources>
<!-- in order to interpolate version from pom into appengine-web.xml -->
<resource>
<directory>${basedir}/src/main/webapp/WEB-INF</directory>
<filtering>true</filtering>
<targetPath>WEB-INF</targetPath>
</resource>
</webResources>
</configuration>
</plugin>

<plugin>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>${appengine.version}</version>
<configuration>
<enableJarClasses>false</enableJarClasses>
<!-- Comment in the below snippet to bind to all IPs instead of just localhost -->
<!-- address>0.0.0.0</address>
<port>8080</port -->
<!-- Comment in the below snippet to enable local debugging with a remove debugger
like those included with Eclipse or IntelliJ -->
<!-- jvmFlags>
<jvmFlag>-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n</jvmFlag>
</jvmFlags -->
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.15</version>
<executions>
<execution>
<id>checkstyle</id>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<failOnViolation>true</failOnViolation>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
10 changes: 10 additions & 0 deletions unittests/src/main/webapp/WEB-INF/appengine-web.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>your-app-id</application>
<version>${appengine.app.version}</version>
<threadsafe>true</threadsafe>

<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
</system-properties>
</appengine-web-app>
13 changes: 13 additions & 0 deletions unittests/src/main/webapp/WEB-INF/logging.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# A default java.util.logging configuration.
# (All App Engine logging is through java.util.logging by default).
#
# To use this configuration, copy it into your application's WEB-INF
# folder and add the following to your appengine-web.xml:
#
# <system-properties>
# <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
# </system-properties>
#

# Set the default logging level for all loggers to WARNING
.level = WARNING
4 changes: 4 additions & 0 deletions unittests/src/main/webapp/WEB-INF/web.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

</web-app>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.google.appengine.samples.unittest;

// [START auth]
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.google.appengine.tools.development.testing.LocalUserServiceTestConfig;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;

public class AuthenticationTest {

private final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalUserServiceTestConfig())
.setEnvIsAdmin(true).setEnvIsLoggedIn(true);

@Before
public void setUp() {
helper.setUp();
}

@After
public void tearDown() {
helper.tearDown();
}

@Test
public void testIsAdmin() {
UserService userService = UserServiceFactory.getUserService();
assertTrue(userService.isUserAdmin());
}
}
// [END auth]
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.google.appengine.samples.unittest;

// [START local_capabilities]
import com.google.appengine.api.capabilities.Capability;
import com.google.appengine.api.capabilities.CapabilityStatus;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.tools.development.testing.LocalCapabilitiesServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.google.apphosting.api.ApiProxy;
import org.junit.After;
import org.junit.Test;

import static org.junit.Assert.*;

public class CapabilitiesTest {

private LocalServiceTestHelper helper;

@After
public void tearDown() {
helper.tearDown();
}

@Test(expected = ApiProxy.CapabilityDisabledException.class)
public void testDisabledDatastore() {
Capability testOne = new Capability("datastore_v3");
CapabilityStatus testStatus = CapabilityStatus.DISABLED;
//Initialize
LocalCapabilitiesServiceTestConfig config =
new LocalCapabilitiesServiceTestConfig().setCapabilityStatus(testOne, testStatus);
helper = new LocalServiceTestHelper(config);
helper.setUp();
FetchOptions fo = FetchOptions.Builder.withLimit(10);
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
assertEquals(0, ds.prepare(new Query("yam")).countEntities(fo));
}
}
// [END local_capabilities]
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.google.appengine.samples.unittest;

// [START taskqueue_example_2]
import com.google.appengine.api.taskqueue.DeferredTask;
import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.google.appengine.tools.development.testing.LocalTaskQueueTestConfig;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

import static org.junit.Assert.*;

public class DeferredTaskTest {

// Unlike CountDownLatch, TaskCountDownlatch lets us reset.
private final LocalTaskQueueTestConfig.TaskCountDownLatch latch =
new LocalTaskQueueTestConfig.TaskCountDownLatch(1);

private final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalTaskQueueTestConfig()
.setDisableAutoTaskExecution(false)
.setCallbackClass(LocalTaskQueueTestConfig.DeferredTaskCallback.class)
.setTaskExecutionLatch(latch));

private static class MyTask implements DeferredTask {
private static boolean taskRan = false;

@Override
public void run() {
taskRan = true;
}
}

@Before
public void setUp() {
helper.setUp();
}

@After
public void tearDown() {
MyTask.taskRan = false;
latch.reset();
helper.tearDown();
}

@Test
public void testTaskGetsRun() throws InterruptedException {
QueueFactory.getDefaultQueue().add(
TaskOptions.Builder.withPayload(new MyTask()));
assertTrue(latch.await(5, TimeUnit.SECONDS));
assertTrue(MyTask.taskRan);
}
}
// [END taskqueue_example_2]
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.google.appengine.samples.unittest;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static com.google.appengine.api.datastore.FetchOptions.Builder.withLimit;
import static org.junit.Assert.*;

// [START HRD_example_2]
// ...
import com.google.appengine.api.datastore.dev.HighRepJobPolicy;

public class LocalCustomPolicyHighRepDatastoreTest {
private static final class CustomHighRepJobPolicy implements HighRepJobPolicy {
static int count = 0;
@Override
public boolean shouldApplyNewJob(Key entityGroup) {
// every other new job fails to apply
return count++ % 2 == 0;
}

@Override
public boolean shouldRollForwardExistingJob(Key entityGroup) {
// every other existing job fails to apply
return count++ % 2 == 0;
}
}

private final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()
.setAlternateHighRepJobPolicyClass(CustomHighRepJobPolicy.class));

@Before
public void setUp() {
helper.setUp();
}

@After
public void tearDown() {
helper.tearDown();
}

@Test
public void testEventuallyConsistentGlobalQueryResult() {
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
ds.put(new Entity("yam")); // applies
ds.put(new Entity("yam")); // does not apply
// first global query only sees the first Entity
assertEquals(1, ds.prepare(new Query("yam")).countEntities(withLimit(10)));
// second global query sees both Entities because we "groom" (attempt to
// apply unapplied jobs) after every query
assertEquals(2, ds.prepare(new Query("yam")).countEntities(withLimit(10)));
}
}
// [END HRD_example_2]
Loading

0 comments on commit 5a6e56a

Please sign in to comment.