diff --git a/Tests/Integration/Delete/EntryTest.php b/Tests/Integration/Delete/EntryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..071f3ad61f202f741f836c3f0816ba8220e6d800
--- /dev/null
+++ b/Tests/Integration/Delete/EntryTest.php
@@ -0,0 +1,166 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery\Tests\Integration\Delete;
+
+
+use calderawp\CalderaFormsQuery\Tests\Integration\IntegrationTestCase;
+
+class EntryTest extends IntegrationTestCase
+{
+
+
+	/**
+	 * Test deleting by entry ID
+	 *
+	 * @covers Entry::deleteByFormId()
+	 */
+	public function testDeleteByFormId()
+	{
+		//Create three entries
+		$this->createEntryWithMockForm();
+		$this->createEntryWithMockForm();
+		$this->createEntryWithMockForm();
+
+		//Delete all entries for this form Id
+		$this->queryWithWPDB(
+			$this
+			->entryDeleteGeneratorFactory()
+			->deleteByFormId($this->mock_form_id)
+			->getPreparedSql()
+		);
+
+		//Prepare SQL to query for entries
+		$entryGenerator = $this->entryGeneratorFactory();
+		$entryGenerator->queryByFormsId($this->mock_form_id);
+		$sql = $entryGenerator->getPreparedSql();
+
+		//No entries -> No results
+		$this->assertSame([], $this->queryWithWPDB($sql));
+
+	}
+
+	/**
+	 * Test we can delete the right entry ID without effecting other entries
+	 *
+	 * @covers Delete::deleteByEntryId()
+	 */
+	public function testDeleteByEntryId()
+	{
+		//Create two entries
+		$entryToDeleteDetails = $this->createEntryWithMockForm();
+		$entryNotToDeleteDetails = $this->createEntryWithMockForm();
+
+		//Delete one of the new entries
+		$this->queryWithWPDB(
+			$this
+				->entryDeleteGeneratorFactory()
+				->deleteByEntryId($entryToDeleteDetails['id'])
+				->getPreparedSql()
+		);
+
+
+		//Prepare SQL to query for the entry that was deleted.
+		$entryGenerator = $this->entryGeneratorFactory();
+		$entryGenerator->queryByEntryId($entryToDeleteDetails['id']);
+		$sql = $entryGenerator->getPreparedSql();
+
+		//No entries -> No results
+		$this->assertSame([], $this->queryWithWPDB($sql));
+
+		//Prepare SQL to query for the entry that was Not deleted.
+		$entryGenerator = $this->entryGeneratorFactory();
+		$entryGenerator->queryByEntryId($entryNotToDeleteDetails['id']);
+		$sql = $entryGenerator->getPreparedSql();
+
+		//One result: This entry should NOT have been deleted
+		$this->assertEquals(1, count($this->queryWithWPDB($sql)));
+	}
+
+	/**
+	 * Test we can delete entries by user ID
+	 *
+	 * @covers Delete::deleteByUserId()
+	 */
+	public function testDeleteByUserId()
+	{
+		//Create two entries for not logged in user
+		$entryDetailsNotLoggedInOne = $this->create_entry($this->mock_form);
+		$entryDetailsNotLoggedInTwo = $this->create_entry($this->mock_form);
+
+		//Create two entries for logged in user
+		$this->factory()->user->create();
+		$userId = $this->factory()->user->create();
+		wp_set_current_user($userId);
+		$this->assertEquals($userId, get_current_user_id());
+		$entryDetailsLoggedInOne = $this->create_entry($this->mock_form);
+		$entryDetailsLoggedInTwo = $this->create_entry($this->mock_form);
+		$entryGeneratorLoggedIn = $this->entryGeneratorFactory();
+		$entryGeneratorLoggedIn->queryByEntryId($entryDetailsLoggedInOne['id']);
+		$sql = $entryGeneratorLoggedIn->getPreparedSql();
+
+		//Delete the entries for logged in user and make sure those entries are gone
+		$this->queryWithWPDB(
+			$this->entryDeleteGeneratorFactory()
+			->deleteByUserId($userId)
+			->getPreparedSql()
+		);
+
+		//Check first entry was deleted
+		$entryGeneratorLoggedIn = $this->entryGeneratorFactory();
+		$entryGeneratorLoggedIn->queryByEntryId($entryDetailsLoggedInOne['id']);
+		$sql = $entryGeneratorLoggedIn->getPreparedSql();
+		$results = $this->queryWithWPDB($sql);
+		$this->assertSame(0, count($results));
+
+		//Check second entry was also deleted
+		$entryGeneratorLoggedIn = $this->entryGeneratorFactory();
+		$entryGeneratorLoggedIn->queryByEntryId($entryDetailsLoggedInTwo['id']);
+		$sql = $entryGeneratorLoggedIn->getPreparedSql();
+		$results = $this->queryWithWPDB($sql);
+		$this->assertSame(0, count($results));
+
+		//Check that we get no result for querying by entries of the user ID we just deleted
+		$entryGenerator = $this->entryGeneratorFactory();
+		$this->assertSame(0, count(
+			$this->queryWithWPDB(
+				$entryGenerator
+					->queryByUserId($userId)
+					->getPreparedSql()
+			)
+		));
+
+		//Test entries from non-logged in user is still there
+		$entryGenerator = $this->entryGeneratorFactory();
+		$this->assertSame(1, count(
+			$this->queryWithWPDB(
+				$entryGenerator
+					->queryByEntryId($entryDetailsNotLoggedInOne['id'])
+					->getPreparedSql()
+			)
+		));
+
+		$entryGenerator = $this->entryGeneratorFactory();
+		$this->assertSame(1, count(
+			$this->queryWithWPDB(
+				$entryGenerator
+					->queryByEntryId($entryDetailsNotLoggedInTwo['id'])
+					->getPreparedSql()
+			)
+		));
+
+
+		$entryGenerator = $this->entryGeneratorFactory();
+		$this->assertSame(2, count(
+			$this->queryWithWPDB(
+				$entryGenerator
+					->queryByUserId(0)
+					->getPreparedSql()
+			)
+		));
+
+
+
+	}
+
+}
\ No newline at end of file
diff --git a/Tests/Integration/Delete/EntryValuesTest.php b/Tests/Integration/Delete/EntryValuesTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..eec8152b71cbe13a76342f6c45293f07c48ab9c9
--- /dev/null
+++ b/Tests/Integration/Delete/EntryValuesTest.php
@@ -0,0 +1,82 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery\Tests\Integration\Delete;
+
+
+use calderawp\CalderaFormsQuery\Delete\EntryValues;
+use calderawp\CalderaFormsQuery\Tests\Integration\IntegrationTestCase;
+use calderawp\CalderaFormsQuery\Tests\Traits\CanCreateEntryWithEmailField;
+
+class EntryValuesTest extends IntegrationTestCase
+{
+
+	use CanCreateEntryWithEmailField;
+	/**
+	 * Test deleting by entry ID
+	 *
+	 * @covers EntryValues::deleteByEntryId()
+	 */
+	public function testDeleteByEntryId()
+	{
+		//Save an entry
+		$entry = $this->createEntryWithMockForm();
+		$entryId = $entry['id'];
+
+		//SQL to count entries
+		$entryValuesQueryGenerator = $this->entryValuesGeneratorFactory();
+		$entryValuesQueryGenerator->queryByEntryId($entryId);
+		$sql = $entryValuesQueryGenerator->getPreparedSql();
+
+		//We have four values -- four fields saved.
+		$results =  $this->queryWithWPDB($sql);
+		$this->assertTrue( ! empty( $results ));
+		$this->assertSame( 4, count( $results ) );
+
+		//Delete entry
+		$this->queryWithWPDB(
+			$this
+				->entryValuesDeleteGeneratorFactory()
+				->deleteByEntryId($entryId)
+				->getPreparedSql()
+		);
+
+		//We have no values -- all fields saved.
+
+		$results =  $this->queryWithWPDB($sql);
+		$this->assertSame( 0, count( $results ) );
+	}
+
+	/**
+	 * Test deleting when field value equals something
+	 *
+	 * @covers EntryValues::deleteByFieldValue()
+	 */
+	public function testDeleteByFieldValueEquals()
+	{
+		$entryId = $this->createEntryWithEmail( 'roy@roysivan.com' );
+		//Delete entry
+		$this->queryWithWPDB(
+			$this
+				->entryValuesDeleteGeneratorFactory()
+				->deleteByFieldValue(
+					$this->getEmailFieldSlug(),
+					'roy@roysivan.com'
+				)
+				->getPreparedSql()
+		);
+
+		//We have no values for this field -- all fields saved.
+		$entryValuesQueryGenerator = $this->entryValuesGeneratorFactory();
+		$entryValuesQueryGenerator->queryByFieldValue(
+			$this->getEmailFieldSlug(),
+			'roy@roysivan.com'
+		);
+		$sql = $entryValuesQueryGenerator->getPreparedSql();
+		$results =  $this->queryWithWPDB($sql);
+		$this->assertSame( 0, count( $results ) );
+
+
+	}
+
+}
\ No newline at end of file
diff --git a/Tests/Integration/EntryQueriesTest.php b/Tests/Integration/EntryQueriesTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c31d0dbf8b58c666b0af3bc687067987cbf32cde
--- /dev/null
+++ b/Tests/Integration/EntryQueriesTest.php
@@ -0,0 +1,61 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery\Tests\Integration;
+
+
+use calderawp\CalderaFormsQuery\EntryQueries;
+use calderawp\CalderaFormsQuery\Tests\Traits\HasFactories;
+use calderawp\CalderaFormsQuery\Tests\Traits\UsersMockFormAsDBForm;
+
+class EntryQueriesTest extends IntegrationTestCase
+{
+	use UsersMockFormAsDBForm;
+	public function setUp()
+	{
+		global $wpdb;
+		$tables = new \Caldera_Forms_DB_Tables($wpdb);
+		$tables->add_if_needed();
+		$this->set_mock_form();
+		$this->mock_form_id = \Caldera_Forms_Forms::import_form( $this->mock_form );
+		$this->mock_form = \Caldera_Forms_Forms::get_form( $this->mock_form_id );
+		parent::setUp();
+	}
+
+	/**
+	 * Test that getResults method runs queries against WordPress correctly
+	 *
+	 * @covers EntryQueries::getResults()
+	 */
+	public function testGetResultsCanDoSQL(){
+		$details = $this->create_entry( $this->mock_form );
+		$details = $this->create_entry( $this->mock_form );
+		global $wpdb;
+		$sql = $wpdb->prepare( "SELECT COUNT(`id`) AS `total` FROM `" . $wpdb->prefix . "cf_form_entries` WHERE `form_id` = %s", $this->mock_form_id );
+		$results = $this->entryQueriesFactory()->getResults( $sql );
+		$this->assertTrue( ! empty( $results ) );
+		$this->assertEquals( 2, $results[0]->total);
+
+		$wpdbDirectResults = $wpdb->get_results( $sql );
+		$this->assertEquals( 2, $wpdbDirectResults[0]->total);
+	}
+
+	/**
+	 * Test that we can run queries and the environment can update DB
+	 *
+	 * @covers EntryQueries::getResults()
+	 */
+	public function testCanQuery()
+	{
+		global $wpdb;
+		$sql = $wpdb->prepare( "SELECT COUNT(`id`) AS `total` FROM `" . $wpdb->prefix . "cf_form_entries` WHERE `form_id` = %s", $this->mock_form_id );
+		$resultsOne = $this->entryQueriesFactory()->getResults( $sql );
+		$this->assertTrue( ! empty( $resultsOne ) );
+
+		$entry_details = $this->create_entry( $this->mock_form );
+		$sql = $wpdb->prepare("SELECT * FROM `" . $wpdb->prefix . "cf_form_entries` WHERE `id` = %s", $entry_details['id'] );
+		$resultsTwo = $this->entryQueriesFactory()->getResults( $sql );
+		$this->assertTrue( ! empty( $resultsTwo ), var_export( $resultsTwo, true ) );
+
+	}
+}
\ No newline at end of file
diff --git a/Tests/Integration/IntegrationTestCase.php b/Tests/Integration/IntegrationTestCase.php
index 0a47f4a8ac123d8c088b114ee5e3c551c81437a1..7613a946b7cacc3b2fe25d129ce015410f6194eb 100755
--- a/Tests/Integration/IntegrationTestCase.php
+++ b/Tests/Integration/IntegrationTestCase.php
@@ -3,6 +3,10 @@
 
 namespace calderawp\CalderaFormsQuery\Tests\Integration;
 
+use calderawp\CalderaFormsQuery\EntryQueries;
+use calderawp\CalderaFormsQuery\Tests\Traits\HasFactories;
+use calderawp\CalderaFormsQuery\Tests\Traits\UsersMockFormAsDBForm;
+
 /**
  * Class IntegrationTestCase
  *
@@ -12,6 +16,91 @@ namespace calderawp\CalderaFormsQuery\Tests\Integration;
  */
 abstract class IntegrationTestCase extends \WP_UnitTestCase
 {
+	use \Caldera_Forms_Has_Data, HasFactories;
+
+	public function setUp()
+	{
+		global $wpdb;
+		$tables = new \Caldera_Forms_DB_Tables($wpdb);
+		$tables->add_if_needed();
+		$this->set_mock_form();
+		$this->mock_form_id = \Caldera_Forms_Forms::import_form( $this->mock_form );
+		$this->mock_form = \Caldera_Forms_Forms::get_form( $this->mock_form_id );
+		parent::setUp();
+	}
+
+	/** @inheritdoc */
+	public function tearDown()
+	{
+		//Delete entries
+		$this->deleteAllEntriesForMockForm();
+		//Delete all forms
+		$forms = \Caldera_Forms_Forms::get_forms();
+		if (!empty($forms)) {
+			foreach ($forms as $form_id => $config) {
+				\Caldera_Forms_Forms::delete_form($form_id);
+			}
+		}
+
+		parent::tearDown();
+	}
+
+	/**
+	 * Gets a WPDB instance
+	 *
+	 * @return \wpdb
+	 */
+	protected function getWPDB()
+	{
+		global $wpdb;
+		return $wpdb;
+	}
+
+	/**
+	 * @return EntryQueries
+	 */
+	protected function entryQueriesFactory()
+	{
+
+		return new EntryQueries(
+			$this->entryGeneratorFactory(),
+			$this->entryValuesGeneratorFactory(),
+			$this->getWPDB()
+		);
+	}
+
+
+	/**
+	 * Use $wpdb->get_results() to do a SQL query directly.
+	 *
+	 * @param $sql
+	 * @return object|null
+	 */
+	protected function queryWithWPDB( $sql )
+	{
+		global  $wpdb;
+		return $wpdb->get_results( $sql );
+	}
+
+	/**
+	 *
+	 */
+	protected function deleteAllEntriesForMockForm()
+	{
+		$this->entryDeleteGeneratorFactory()->deleteByFormId($this->mock_form_id);
+	}
+
+	/**
+	 * @return array
+	 */
+	protected function createEntryWithMockForm()
+	{
+		return $this->create_entry( $this->mock_form );
+	}
+
+
+
+
 
 
 }
diff --git a/Tests/Integration/Select/EntryTest.php b/Tests/Integration/Select/EntryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a3165568a56cd3b48b161b5674576dbf641969af
--- /dev/null
+++ b/Tests/Integration/Select/EntryTest.php
@@ -0,0 +1,143 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery\Tests\Integration\Select;
+
+
+use calderawp\CalderaFormsQuery\Tests\Integration\IntegrationTestCase;
+use calderawp\CalderaFormsQuery\Tests\Traits\HasFactories;
+use calderawp\CalderaFormsQuery\Tests\Traits\UsersMockFormAsDBForm;
+
+class EntryTest extends IntegrationTestCase
+{
+
+	/** @inheritdoc */
+	protected $mock_form_id;
+	/** @inheritdoc */
+	protected $mock_form;
+	/** @inheritdoc */
+
+
+	/**
+	 * Test query by form ID
+	 *
+	 * @covers Entry::queryByFormsId()
+	 */
+	public function testQueryByFormsId()
+	{
+		$entryGenerator = $this->entryGeneratorFactory();
+		$entryGenerator->queryByFormsId($this->mock_form_id);
+		$sql = $entryGenerator->getPreparedSql();
+
+		//No entries -> No results
+		$this->assertSame([], $this->queryWithWPDB( $sql) );
+
+
+		//One entry -> One result, with the right form ID.
+		$this->createEntryWithMockForm();
+		$results = $this->queryWithWPDB( $sql);
+		$this->assertTrue( ! empty( $this->queryWithWPDB( $sql) ) );
+		$this->assertSame( 1, count($results));
+		$this->assertSame( $results[0]->form_id, $this->mock_form_id );
+
+		//Two entries -> Two result, with the right form ID.
+		$this->createEntryWithMockForm();
+		$results = $this->queryWithWPDB( $sql);
+		$this->assertTrue( ! empty( $this->queryWithWPDB( $sql) ) );
+		$this->assertSame( 2, count($results));
+		$this->assertSame( $results[0]->form_id, $this->mock_form_id );
+		$this->assertSame( $results[1]->form_id, $this->mock_form_id );
+
+	}
+
+	/**
+	 * Test query by entry ID
+	 *
+	 * @covers Entry::queryByEntryId()
+	 */
+	public function testQueryByEntryId()
+	{
+		$entry = $this->createEntryWithMockForm();
+		$entryGenerator = $this->entryGeneratorFactory();
+		//No results for a non-existent entry
+		$entryGenerator->queryByEntryId(42);
+		$sql = $entryGenerator->getPreparedSql();
+		$this->assertSame( [],  $this->queryWithWPDB($sql));
+
+		//One entry: one result with the correct ID
+		$entryGenerator = $this->entryGeneratorFactory();
+		$entryGenerator->queryByEntryId($entry['id']);
+		$sql = $entryGenerator->getPreparedSql();
+		$results =  $this->queryWithWPDB($sql);
+		$this->assertTrue( ! empty( $results ));
+		$this->assertSame( 1, count( $results ) );
+		$this->assertEquals( $results[0]->id, $entry['id']);
+
+		//Two more entries: one result for original entry ID
+		$this->createEntryWithMockForm();
+		$this->createEntryWithMockForm();
+		$entryGenerator = $this->entryGeneratorFactory();
+		$entryGenerator->queryByEntryId($entry['id']);
+		$sql = $entryGenerator->getPreparedSql();
+		$results =  $this->queryWithWPDB($sql);
+		$this->assertTrue( ! empty( $results ));
+		$this->assertSame( 1, count( $results ) );
+	}
+
+	/**
+	 * Test query by user ID
+	 *
+	 * @covers Entry::queryByUserId()
+	 */
+	/**
+	 * Test query by user ID
+	 *
+	 * @covers Entry::queryByUserId()
+	 */
+	public function testQueryByUserId()
+	{
+
+		//Create an entry for without a user
+		$this->deleteAllEntriesForMockForm();
+		$entryDetailsNotLoggedIn = $this->create_entry($this->mock_form);
+
+		//Create an entry for a known user.
+		$this->factory()->user->create();
+		$userId = $this->factory()->user->create();
+		wp_set_current_user( $userId );
+		$this->assertEquals( $userId, get_current_user_id() );
+		$entryDetailsLoggedIn = $this->create_entry($this->mock_form);
+
+		//Make sure there is one entry with with this user
+		$entryGeneratorLoggedIn = $this->entryGeneratorFactory();
+		$entryGeneratorLoggedIn->queryByEntryId($entryDetailsLoggedIn['id']);
+		$sql= $entryGeneratorLoggedIn->getPreparedSql();
+		$resultsByEntryId =  $this->queryWithWPDB($sql);
+		$this->assertTrue( ! empty( $resultsByEntryId ));
+		$this->assertSame( 1, count( $resultsByEntryId ) );
+		$this->assertEquals( $userId, $resultsByEntryId[0]->user_id );
+
+		//Test that query by User ID gets the right entry
+		$entryGeneratorLoggedIn = $this->entryGeneratorFactory();
+		$entryGeneratorLoggedIn->queryByUserId($userId);
+		$sql= $entryGeneratorLoggedIn->getPreparedSql();
+		$resultsByUserId =  $this->queryWithWPDB($sql);
+		$this->assertEqualSets((array)$resultsByEntryId[0], (array)$resultsByUserId[0]);
+
+		//Test that non-logged in user is tracked in DB as 0, not some actual user ID and we can select that way
+		$entryGeneratorNotLoggedIn = $this->entryGeneratorFactory();
+		$entryGeneratorNotLoggedIn->queryByEntryId($entryDetailsNotLoggedIn['id'] );
+		$sql= $entryGeneratorLoggedIn->getPreparedSql();
+		$resultsByEntryId =  $this->queryWithWPDB($sql);
+		$this->assertTrue( ! empty( $resultsByEntryId ));
+		$this->assertSame( 1, count( $resultsByEntryId ) );
+		$this->assertEquals( $userId, $resultsByEntryId[0]->user_id );
+
+	}
+
+
+
+
+
+
+}
\ No newline at end of file
diff --git a/Tests/Integration/Select/EntryValuesTest.php b/Tests/Integration/Select/EntryValuesTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3f21d7c3fdd278bc3fa3817748cbd9aa7b0108f7
--- /dev/null
+++ b/Tests/Integration/Select/EntryValuesTest.php
@@ -0,0 +1,125 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery\Tests\Integration\Select;
+
+
+
+use calderawp\CalderaFormsQuery\Tests\Integration\IntegrationTestCase;
+use calderawp\CalderaFormsQuery\Tests\Traits\CanCreateEntryWithEmailField;
+
+class EntryValuesTest extends IntegrationTestCase
+{
+	use CanCreateEntryWithEmailField;
+
+	/**
+	 * Test query by entry ID
+	 *
+	 * @covers EntryValues::queryByEntryId()
+	 */
+	public function testQueryByEntryId()
+	{
+		$entry = $this->createEntryWithMockForm();
+		$entryValuesQueryGenerator = $this->entryValuesGeneratorFactory();
+		$entryValuesQueryGenerator->queryByEntryId($entry['id']);
+		$sql = $entryValuesQueryGenerator->getPreparedSql();
+		$results =  $this->queryWithWPDB($sql);
+		$this->assertTrue( ! empty( $results ));
+		$this->assertSame( 4, count( $results ) );
+		$this->assertEquals( $results[0]->entry_id, $entry['id']);
+		$this->assertEquals( $results[1]->entry_id, $entry['id']);
+		$this->assertEquals( $results[2]->entry_id, $entry['id']);
+		$this->assertEquals( $results[3]->entry_id, $entry['id']);
+
+	}
+
+	/**
+	 * Test query by field where field value equals a value
+	 *
+	 * @covers \calderawp\CalderaFormsQuery\Select\EntryValues::queryByFieldValue()
+	 */
+	public function testQueryByFieldValueEquals()
+	{
+		//Entry with no real email
+		$this->createEntryWithMockForm();
+		//Create entries for each of two emails
+		$emailOne = 'one@hiroy.club';
+		$emailTwo = 'two@hiroy.club';
+		$this->createEntryWithEmail( $emailOne );
+		$this->createEntryWithEmail( $emailTwo );
+
+		//One entry when querying by first email
+		$entryValuesQueryGenerator = $this->entryValuesGeneratorFactory();
+
+		$this->assertSame( 1, count(
+			$this->queryWithWPDB(
+				$entryValuesQueryGenerator
+					->queryByFieldValue(
+						$this->getEmailFieldSlug(),
+						$emailOne
+					)
+				->getPreparedSql()
+			)
+		) );
+
+		//One entry when querying by second email
+		$entryValuesQueryGenerator = $this->entryValuesGeneratorFactory();
+		$this->assertSame( 1, count(
+			$this->queryWithWPDB(
+				$entryValuesQueryGenerator
+					->queryByFieldValue(
+						$this->getEmailFieldSlug(),
+						$emailTwo
+					)
+				->getPreparedSql()
+			)
+		) );
+
+	}
+
+	/**
+	 * Test query by field where field does not equals a value
+	 *
+	 * @covers \calderawp\CalderaFormsQuery\Select\EntryValues::queryByFieldValue()
+	 */
+	public function testQueryByFieldValueNotEquals()
+	{
+		//Entry with no real email
+		$this->createEntryWithMockForm();
+		//Create entries for each of two emails
+		$emailOne = 'one@hiroy.club';
+		$emailTwo = 'two@hiroy.club';
+		$this->createEntryWithEmail( $emailOne );
+		$this->createEntryWithEmail( $emailTwo );
+
+		//Two entries when querying by NOT first email
+		$entryValuesQueryGenerator = $this->entryValuesGeneratorFactory();
+		$this->assertSame( 2, count(
+			$this->queryWithWPDB(
+				$entryValuesQueryGenerator
+					->queryByFieldValue(
+						$this->getEmailFieldSlug(),
+						$emailOne,
+						'notEquals'
+					)
+				->getPreparedSql()
+			)
+		) );
+
+		//Two entries when querying by NOT second email
+		$entryValuesQueryGenerator = $this->entryValuesGeneratorFactory();
+		$this->assertSame( 2, count(
+			$this->queryWithWPDB(
+				$entryValuesQueryGenerator
+					->queryByFieldValue(
+						$this->getEmailFieldSlug(),
+						$emailTwo,
+						'notEquals'
+					)
+				->getPreparedSql()
+			)
+		) );
+
+	}
+
+}
\ No newline at end of file
diff --git a/Tests/Integration/TestsTest.php b/Tests/Integration/TestsTest.php
index de82c30702234a40314079157b531485ce22604a..18cef29724b10b03e33adc63fcef8542ba36eb7e 100644
--- a/Tests/Integration/TestsTest.php
+++ b/Tests/Integration/TestsTest.php
@@ -3,6 +3,10 @@
 
 namespace calderawp\CalderaFormsQuery\Tests\Integration;
 
+use calderawp\CalderaFormsQuery\EntryQueries;
+use calderawp\CalderaFormsQuery\Select\Entry;
+use calderawp\CalderaFormsQuery\Select\EntryValues;
+
 /**
  * Class TestsTest
  *
@@ -11,6 +15,8 @@ namespace calderawp\CalderaFormsQuery\Tests\Integration;
  */
 class TestsTest extends IntegrationTestCase
 {
+	//Using this so we can test that CF's testing traits are available
+	use \Caldera_Forms_Has_Mock_Form;
 
 	/**
 	 * Check that Caldera Forms is usable
@@ -21,4 +27,28 @@ class TestsTest extends IntegrationTestCase
 		$this->assertTrue( class_exists( '\Caldera_Forms' ) );
 	}
 
+	/**
+	 * Make sure the trait worked
+	 */
+	public function testMockForm()
+	{
+		$this->set_mock_form();
+		$this->assertTrue( is_array( $this->mock_form  ) );
+	}
+
+	/**
+	 * Test that factories work for integration tests
+	 *
+	 * @covers HasFactories::entryQueriesFactory()
+	 * @covers HasFactories::entryValuesGeneratorFactory()
+	 * @covers HasFactories::entryGeneratorFactory()
+	 */
+	public function testFactory()
+	{
+		$this->assertTrue(is_a($this->entryQueriesFactory(), EntryQueries::class));
+		$this->assertTrue(is_a($this->entryValuesGeneratorFactory(), EntryValues::class));
+		$this->assertTrue(is_a($this->entryGeneratorFactory(), Entry::class));
+
+	}
+
 }
\ No newline at end of file
diff --git a/Tests/Mock/wpdb.php b/Tests/Mock/wpdb.php
index d2a09e0807922ddec6a5a2be284578ba0b0fbf15..21412e6db49b38532b7a400bb25e011b4ac971e9 100644
--- a/Tests/Mock/wpdb.php
+++ b/Tests/Mock/wpdb.php
@@ -6,6 +6,16 @@ if( class_exists( 'wpdb')){
 class wpdb
 {
 
+	/**
+	 * @var string
+	 */
+	public $prefix = 'wp_';
+
+	/**
+	 * @param null $query
+	 * @param string $output
+	 * @return array
+	 */
 	public function get_results( $query = null, $output = OBJECT )
 	{
 		return [
diff --git a/Tests/Traits/CanCreateEntryWithEmailField.php b/Tests/Traits/CanCreateEntryWithEmailField.php
new file mode 100644
index 0000000000000000000000000000000000000000..c3de5aff499538d4b630515bd11298d82bda84cf
--- /dev/null
+++ b/Tests/Traits/CanCreateEntryWithEmailField.php
@@ -0,0 +1,56 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery\Tests\Traits;
+
+/**
+ * Trait CreatesEntryWithEmailField
+ *
+ * Helper functions for testing entry by email
+ */
+trait CanCreateEntryWithEmailField
+{
+	use \Caldera_Forms_Has_Mock_Form;
+
+	/**
+	 * Create an entry associated with an email
+	 *
+	 * @param string $email
+	 *
+	 * @return int
+	 */
+	protected function createEntryWithEmail( $email = 'hiroy@hiroy.club' )
+	{
+		$fieldData = [];
+		$emailFieldConfig = $this->getEmailField();
+		foreach( $this->mock_form[ 'fields' ] as $fieldId => $fieldConfig ){
+			if ( $fieldId === $emailFieldConfig[ 'ID'] ) {
+				$fieldData[ $fieldId ] = $email;
+			} else {
+				$fieldData[ $fieldId ] = rand() . $fieldId;
+			}
+		}
+
+		return \Caldera_Forms_Save_Final::create_entry( $this->mock_form, $fieldData  );
+	}
+
+	/**
+	 * Get the email field's config array
+	 *
+	 * @return array|bool
+	 */
+	protected function getEmailField()
+	{
+		return \Caldera_Forms_Field_Util::get_field_by_slug( 'email', $this->mock_form );
+	}
+
+	/**
+	 * Get slug of email field
+	 *
+	 * @return string
+	 */
+	protected function getEmailFieldSlug()
+	{
+		return $this->getEmailField()[ 'slug' ];
+	}
+}
\ No newline at end of file
diff --git a/Tests/Traits/HasFactories.php b/Tests/Traits/HasFactories.php
new file mode 100644
index 0000000000000000000000000000000000000000..ad3e5eb5cf0d80fb8c5e28850067247676c5a389
--- /dev/null
+++ b/Tests/Traits/HasFactories.php
@@ -0,0 +1,112 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery\Tests\Traits;
+
+use calderawp\CalderaFormsQuery\EntryQueries;
+
+trait HasFactories
+{
+
+	/**
+	 * @return \calderawp\CalderaFormsQuery\Select\Entry
+	 */
+	protected function entryGeneratorFactory()
+	{
+		return new \calderawp\CalderaFormsQuery\Select\Entry(
+			$this->mySqlBuilderFactory(),
+			$this->entryTableName()
+		);
+	}
+
+	/**
+	 * @return \calderawp\CalderaFormsQuery\Delete\Entry
+	 */
+	protected function entryDeleteGeneratorFactory()
+	{
+		return new \calderawp\CalderaFormsQuery\Delete\Entry(
+			$this->mySqlBuilderFactory(),
+			$this->entryTableName()
+		);
+	}
+
+
+	/**
+	 * @return \calderawp\CalderaFormsQuery\Select\EntryValues
+	 */
+	protected function entryValuesGeneratorFactory()
+	{
+		return new \calderawp\CalderaFormsQuery\Select\EntryValues(
+			$this->mySqlBuilderFactory(),
+			$this->entryValueTableName()
+		);
+	}
+	/**
+	 * @return \calderawp\CalderaFormsQuery\Delete\EntryValues
+	 */
+	protected function entryValuesDeleteGeneratorFactory()
+	{
+		return new \calderawp\CalderaFormsQuery\Delete\EntryValues(
+			$this->mySqlBuilderFactory(),
+			$this->entryValueTableName()
+		);
+	}
+
+
+
+	/**
+	 * @return \calderawp\CalderaFormsQuery\MySqlBuilder
+	 */
+	protected function mySqlBuilderFactory()
+	{
+		return new \calderawp\CalderaFormsQuery\MySqlBuilder();
+	}
+
+
+	/**
+	 * @return EntryQueries
+	 */
+	protected function entryQueriesFactory()
+	{
+
+		return new EntryQueries(
+			$this->entryGeneratorFactory(),
+			$this->entryValuesGeneratorFactory(),
+			$this->getWPDB()
+		);
+	}
+
+	/**
+	 * Gets a WPDB instance
+	 *
+	 * @return \wpdb
+	 */
+	protected function getWPDB()
+	{
+		global $wpdb;
+		if (! class_exists( '\WP_User')) {
+			include_once dirname(dirname(__FILE__)) . '/Mock/wpdb.php';
+		}
+
+		if (! $wpdb) {
+			$wpdb = new \wpdb('', '', '', '');
+		}
+		return $wpdb;
+	}
+
+	/**
+	 * @return string
+	 */
+	protected function entryValueTableName(): string
+	{
+		return "{$this->getWPDB()->prefix}cf_form_entry_values";
+	}
+
+	/**
+	 * @return string
+	 */
+	protected function entryTableName(): string
+	{
+		return "{$this->getWPDB()->prefix}cf_form_entries";
+	}
+}
diff --git a/Tests/Traits/UsersMockFormAsDBForm.php b/Tests/Traits/UsersMockFormAsDBForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..595bc9adbdf8fd3a49309aee42d2ebfee32d5313
--- /dev/null
+++ b/Tests/Traits/UsersMockFormAsDBForm.php
@@ -0,0 +1,28 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery\Tests\Traits;
+
+trait UsersMockFormAsDBForm
+{
+
+	use \Caldera_Forms_Has_Data, HasFactories;
+	/** @inheritdoc */
+	protected $mock_form_id;
+	/** @inheritdoc */
+	protected $mock_form;
+	/** @inheritdoc */
+
+	public function setUp()
+	{
+		global $wpdb;
+		$tables = new \Caldera_Forms_DB_Tables($wpdb);
+		$tables->add_if_needed();
+		$this->set_mock_form();
+		$this->mock_form_id = \Caldera_Forms_Forms::import_form($this->mock_form);
+		$this->mock_form = \Caldera_Forms_Forms::get_form($this->mock_form_id);
+		parent::setUp();
+	}
+
+
+}
diff --git a/Tests/Unit/Delete/DeleteQueryBuilderTest.php b/Tests/Unit/Delete/DeleteQueryBuilderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e7ad222a066b00d4eedcc4f6ce0954539d0c9c70
--- /dev/null
+++ b/Tests/Unit/Delete/DeleteQueryBuilderTest.php
@@ -0,0 +1,102 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery\Tests\Unit\Delete;
+
+
+use calderawp\CalderaFormsQuery\Delete\DeleteQueryBuilder;
+use calderawp\CalderaFormsQuery\MySqlBuilder;
+use calderawp\CalderaFormsQuery\Tests\Unit\TestCase;
+use NilPortugues\Sql\QueryBuilder\Manipulation\Delete;
+
+class DeleteQueryBuilderTest extends TestCase
+{
+
+	/**
+	 * Test table names
+	 *
+	 * @covers DeleteQueryBuilder::getTableName()
+	 * @covers DeleteQueryBuilder::$tableName
+	 */
+	public function testGetTableName()
+	{
+		$entry = $this->entryDeleteGeneratorFactory();
+		$this->assertEquals($this->entryTableName(), $entry->getTableName());
+
+		$entryValues = $this->entryValuesDeleteGeneratorFactory();
+		$this->assertSame($this->entryValueTableName(), $entryValues->getTableName());
+	}
+
+	/**
+	 * Test getting SQL builder
+	 *
+	 * @covers DeleteQueryBuilder::getBuilder()
+	 * @covers DeleteQueryBuilder::$builder
+	 */
+	public function testGetBuilder()
+	{
+		$entry = $this->entryDeleteGeneratorFactory();
+		$this->assertTrue(is_a($entry->getBuilder(), MySqlBuilder::class));
+
+		$entryValues = $this->entryValuesDeleteGeneratorFactory();
+		$this->assertTrue(is_a($entryValues->getBuilder(), MySqlBuilder::class));
+
+	}
+
+	/**
+	 * Ensure that getDeleteQuery returns the delete query
+	 *
+	 * @covers DeleteQueryBuilder::getDeleteQuery()
+	 * @covers DeleteQueryBuilder::$deleteQuery
+	 */
+	public function testGetDeleteQueryReturnsDeleteQuery()
+	{
+		$entry = $this->entryDeleteGeneratorFactory();
+		$this->assertTrue(is_a($entry->getDeleteQuery(), Delete::class));
+
+		$entryValues = $this->entryValuesDeleteGeneratorFactory();
+		$this->assertTrue(is_a($entryValues->getDeleteQuery(), Delete::class));
+
+	}
+
+	/**
+	 * Ensure deleteQuery and currentQuery are the same
+	 *
+	 * @covers DeleteQueryBuilder::getDeleteQuery()
+	 * @covers DeleteQueryBuilder::getCurrentQuery()
+	 */
+	public function testGetDeleteQueryAndCurrentQueryAreSame()
+	{
+		$entry = $this->entryDeleteGeneratorFactory();
+		$this->assertSame( $entry->getDeleteQuery(), $entry->getCurrentQuery() );
+
+		$entryValues = $this->entryValuesDeleteGeneratorFactory();
+		$this->assertSame( $entryValues->getDeleteQuery(), $entryValues->getCurrentQuery() );
+	}
+
+	/**
+	 * Test table name is set on query builder correctly
+	 *
+	 * @covers DeleteQueryBuilder::getDeleteQuery()
+	 */
+	public function testTableNameForQueryBuilder()
+	{
+		$entry = $this->entryDeleteGeneratorFactory();
+		$this->assertEquals(
+			$this->entryTableName(),
+			$entry
+			->getDeleteQuery()
+			->getTable()
+			->getName()
+		);
+
+		$entryValues = $this->entryValuesDeleteGeneratorFactory();
+		$this->assertEquals(
+			$this->entryValueTableName(),
+			$entryValues
+				->getDeleteQuery()
+				->getTable()
+				->getName()
+		);
+	}
+}
\ No newline at end of file
diff --git a/Tests/Unit/EntryQueriesTest.php b/Tests/Unit/EntryQueriesTest.php
index 30f037f2c9aa628a16098cda09636ea0ea021a12..b87a1b34ffd82ba99eb09ec8bf54597ddbf75445 100644
--- a/Tests/Unit/EntryQueriesTest.php
+++ b/Tests/Unit/EntryQueriesTest.php
@@ -28,20 +28,21 @@ class EntryQueriesTest extends TestCase
 	 *
 	 * @covers EntryQueries::getEntryValueGenerator()
 	 * @covers EntryQueries::$entryValueGenerator
-	 */public function testGetEntryValueGenerator()
+	 */
+	public function testGetEntryValueGenerator()
 	{
 		$queries = $this->entryQueriesFactory();
 		$this->assertTrue(is_a($queries->getEntryValueGenerator(), EntryValues::class));
-}
+	}
 
 	/**
 	 * Test that getResults method returns an array
 	 *
 	 * @covers EntryQueries::getResults()
 	 */
-public function testGetResults()
-{
-	$queries = $this->entryQueriesFactory();
-	$this->assertTrue(is_array($queries->getResults("SELECT `roy` FROM sivan WHERE mike = 'roy'")));
-}
+	public function testGetResults()
+	{
+		$queries = $this->entryQueriesFactory();
+		$this->assertTrue(is_array($queries->getResults("SELECT `roy` FROM sivan WHERE mike = 'roy'")));
+	}
 }
diff --git a/Tests/Unit/MySqlBuilderTest.php b/Tests/Unit/MySqlBuilderTest.php
index 494e46b1999bc833e7c04ba645609ce9c7a84f45..0a608d877693db95e90b595243efd480b634fbbf 100644
--- a/Tests/Unit/MySqlBuilderTest.php
+++ b/Tests/Unit/MySqlBuilderTest.php
@@ -18,7 +18,7 @@ class MySqlBuilderTest extends TestCase
 	public function testSubstitutions()
 	{
 
-		$builder = $this->MySqlBuilderFactory();
+		$builder = $this->mySqlBuilderFactory();
 		$query = new \NilPortugues\Sql\QueryBuilder\Manipulation\Select('foo');
 
 		$query
diff --git a/Tests/Unit/Select/EntryTest.php b/Tests/Unit/Select/EntryTest.php
index e54c799a1803a18409fd86e2f5599d1de1bdef58..22015f713cdb6634260d4769711aea32b2f011c7 100644
--- a/Tests/Unit/Select/EntryTest.php
+++ b/Tests/Unit/Select/EntryTest.php
@@ -16,7 +16,7 @@ class EntryTest extends TestCase
 	 */
 	public function testQueryByFormsId()
 	{
-		$expectedSql = "SELECT `wp_cf_form_entries`.* FROM `wp_cf_form_entries` WHERE (`wp_cf_form_entries`.`form_id` = 'cf12345')";
+		$expectedSql = "SELECT `{$this->entryTableName()}`.* FROM `wp_cf_form_entries` WHERE (`{$this->entryTableName()}`.`form_id` = 'cf12345')";
 		$entryGenerator = $this->entryGeneratorFactory();
 		$generator = $entryGenerator->queryByFormsId('cf12345');
 		$this->assertTrue($this->isAEntry($generator));
@@ -32,7 +32,7 @@ class EntryTest extends TestCase
 	 */
 	public function testQueryByEntryId()
 	{
-		$expectedSql = "SELECT `wp_cf_form_entries`.* FROM `wp_cf_form_entries` WHERE (`wp_cf_form_entries`.`id` = '42')";
+		$expectedSql = "SELECT `{$this->entryTableName()}`.* FROM `{$this->entryTableName()}` WHERE (`{$this->entryTableName()}`.`id` = '42')";
 		$entryGenerator = $this->entryGeneratorFactory();
 		$generator = $entryGenerator->queryByEntryId(42);
 		$this->assertTrue($this->isAEntry($generator));
@@ -48,7 +48,7 @@ class EntryTest extends TestCase
 	 */
 	public function testQueryByUserId()
 	{
-		$expectedSql = "SELECT `wp_cf_form_entries`.* FROM `wp_cf_form_entries` WHERE (`wp_cf_form_entries`.`user_id` = '42')";
+		$expectedSql = "SELECT `{$this->entryTableName()}`.* FROM `{$this->entryTableName()}` WHERE (`{$this->entryTableName()}`.`user_id` = '42')";
 		$entryGenerator = $this->entryGeneratorFactory();
 		$generator = $entryGenerator->queryByUserId(42);
 		$this->assertTrue($this->isAEntry($generator));
diff --git a/Tests/Unit/Select/EntryValuesTest.php b/Tests/Unit/Select/EntryValuesTest.php
index 87f735b5c3ab2a99fe711bb8c2e43405acee6827..3e6828788ba23bbd6efc4be5c52a85b0a3357444 100644
--- a/Tests/Unit/Select/EntryValuesTest.php
+++ b/Tests/Unit/Select/EntryValuesTest.php
@@ -15,7 +15,7 @@ class EntryValuesTest extends TestCase
 	 */
 	public function testQueryByFieldValueEquals()
 	{
-		$expectedSql = "SELECT `cf_form_entry_values`.* FROM `cf_form_entry_values` WHERE (`cf_form_entry_values`.`value` = 'josh@calderawp.com') AND (`cf_form_entry_values`.`slug` = 'email_address')";
+		$expectedSql = "SELECT `{$this->entryValueTableName()}`.* FROM `{$this->entryValueTableName()}` WHERE (`{$this->entryValueTableName()}`.`value` = 'josh@calderawp.com') AND (`{$this->entryValueTableName()}`.`slug` = 'email_address')";
 
 		$entryValues = $this->entryValuesGeneratorFactory();
 		$generator = $entryValues->queryByFieldValue('email_address', 'josh@calderawp.com');
@@ -32,7 +32,7 @@ class EntryValuesTest extends TestCase
 	 */
 	public function testQueryByFieldValueNotEquals()
 	{
-		$expectedSql = "SELECT `cf_form_entry_values`.* FROM `cf_form_entry_values` WHERE (`cf_form_entry_values`.`value` <> 'josh@calderawp.com') AND (`cf_form_entry_values`.`slug` = 'email_address')";
+		$expectedSql = "SELECT `{$this->entryValueTableName()}`.* FROM `{$this->entryValueTableName()}` WHERE (`{$this->entryValueTableName()}`.`value` <> 'josh@calderawp.com') AND (`{$this->entryValueTableName()}`.`slug` = 'email_address')";
 		$entryValues = $this->entryValuesGeneratorFactory();
 		$generator =$entryValues->queryByFieldValue('email_address', 'josh@calderawp.com', 'notEquals');
 		$this->assertTrue($this->isAEntryValues($generator));
@@ -49,7 +49,7 @@ class EntryValuesTest extends TestCase
 	 */
 	public function testQueryByFieldValueLike()
 	{
-		$expectedSql = "SELECT `cf_form_entry_values`.* FROM `cf_form_entry_values` WHERE (`cf_form_entry_values`.`value` LIKE %josh@calderawp.com%)";
+		$expectedSql = "SELECT `{$this->entryValueTableName()}`.* FROM `{$this->entryValueTableName()}` WHERE (`{$this->entryValueTableName()}`.`value` LIKE '\%josh@calderawp.com\%')";
 		
 		$entryValues = $this->entryValuesGeneratorFactory();
 		$generator = $entryValues->queryByFieldValue('email_address', 'josh@calderawp.com', 'like');
@@ -66,7 +66,7 @@ class EntryValuesTest extends TestCase
 	 */
 	public function testQueryByEntryId()
 	{
-		$expectedSql = "SELECT `cf_form_entry_values`.* FROM `cf_form_entry_values` WHERE (`cf_form_entry_values`.`entry_id` = '42')";
+		$expectedSql = "SELECT `{$this->entryValueTableName()}`.* FROM `{$this->entryValueTableName()}` WHERE (`{$this->entryValueTableName()}`.`entry_id` = '42')";
 		$entryValues = $this->entryValuesGeneratorFactory();
 		$generator = $entryValues->queryByEntryId(42);
 		$this->assertTrue($this->isAEntryValues($generator));
diff --git a/Tests/Unit/Select/SelectQueryBuilderTest.php b/Tests/Unit/Select/SelectQueryBuilderTest.php
index 78dac1e12067b6d7742b915a46061fd19379e5b2..2c3c8f191944db5e83977ac030e97db54570e370 100644
--- a/Tests/Unit/Select/SelectQueryBuilderTest.php
+++ b/Tests/Unit/Select/SelectQueryBuilderTest.php
@@ -22,10 +22,10 @@ class SelectQueryBuilderTest extends TestCase
 	public function testGetTableName()
 	{
 		$entry = $this->entryGeneratorFactory();
-		$this->assertEquals('wp_cf_form_entries', $entry->getTableName());
+		$this->assertEquals($this->entryTableName(), $entry->getTableName());
 
 		$entryValues = $this->entryValuesGeneratorFactory();
-		$this->assertSame('cf_form_entry_values', $entryValues->getTableName());
+		$this->assertSame($this->entryValueTableName(), $entryValues->getTableName());
 	}
 
 	/**
@@ -47,7 +47,7 @@ class SelectQueryBuilderTest extends TestCase
 	 * Test getting select query generator
 	 *
 	 * @covers SelectQueryBuilder::getSelectQuery()
-	 * @covers SelectQueryBuilder::$query
+	 * @covers SelectQueryBuilder::$selectQuery
 	 */
 	public function testGetSelectQuery()
 	{
@@ -66,7 +66,7 @@ class SelectQueryBuilderTest extends TestCase
 	public function testAddOrderByDesc()
 	{
 		$entry = $this->entryGeneratorFactory();
-		$expectedSql = "SELECT `wp_cf_form_entries`.* FROM `wp_cf_form_entries` WHERE (`wp_cf_form_entries`.`form_id` = 'cf12345') ORDER BY `wp_cf_form_entries`.`form_id` DESC";
+		$expectedSql = "SELECT `{$this->entryTableName()}`.* FROM `{$this->entryTableName()}` WHERE (`{$this->entryTableName()}`.`form_id` = 'cf12345') ORDER BY `{$this->entryTableName()}`.`form_id` DESC";
 		$entry->queryByFormsId('cf12345');
 		$entry->addOrderBy('form_id', false);
 		$actualSql = $entry->getPreparedSql();
@@ -81,7 +81,7 @@ class SelectQueryBuilderTest extends TestCase
 	public function testAddOrderByAsc()
 	{
 		$entry = $this->entryGeneratorFactory();
-		$expectedSql = "SELECT `wp_cf_form_entries`.* FROM `wp_cf_form_entries` WHERE (`wp_cf_form_entries`.`form_id` = 'cf12345') ORDER BY `wp_cf_form_entries`.`form_id` ASC";
+		$expectedSql = "SELECT `{$this->entryTableName()}`.* FROM `{$this->entryTableName()}` WHERE (`{$this->entryTableName()}`.`form_id` = 'cf12345') ORDER BY `{$this->entryTableName()}`.`form_id` ASC";
 		$entry->queryByFormsId('cf12345');
 		$entry->addOrderBy('form_id');
 		$actualSql = $entry->getPreparedSql();
@@ -100,7 +100,7 @@ class SelectQueryBuilderTest extends TestCase
 	}
 
 	/**
-	 * Test the SDESC constant
+	 * Test the DESC constant
 	 *
 	 * @covers SelectQueryBuilder::DESC
 	 */
diff --git a/Tests/Unit/TestCase.php b/Tests/Unit/TestCase.php
index 9e4308e1ae77f1b222d065e1483e7260db0f58cf..d174e3a844362fe3c3950073793ef214ff4e237f 100755
--- a/Tests/Unit/TestCase.php
+++ b/Tests/Unit/TestCase.php
@@ -6,6 +6,7 @@ namespace calderawp\CalderaFormsQuery\Tests\Unit;
 //Import PHP unit test case.
 //Must be aliased to avoid having two classes of same name in scope.
 use calderawp\CalderaFormsQuery\EntryQueries;
+use calderawp\CalderaFormsQuery\Tests\Traits\HasFactories;
 use PHPUnit\Framework\TestCase as FrameworkTestCase;
 
 /**
@@ -16,45 +17,5 @@ use PHPUnit\Framework\TestCase as FrameworkTestCase;
  */
 abstract class TestCase extends FrameworkTestCase
 {
-	/**
-	 * @return \calderawp\CalderaFormsQuery\Select\EntryValues
-	 */
-	protected function entryValuesGeneratorFactory()
-	{
-		return new \calderawp\CalderaFormsQuery\Select\EntryValues(
-			$this->MySqlBuilderFactory(),
-			'cf_form_entry_values'
-		);
-	}
-
-	/**
-	 * @return \calderawp\CalderaFormsQuery\Select\Entry
-	 */
-	protected function entryGeneratorFactory()
-	{
-		return new \calderawp\CalderaFormsQuery\Select\Entry(
-			$this->MySqlBuilderFactory(),
-			'wp_cf_form_entries'
-		);
-	}
-
-	/**
-	 * @return \calderawp\CalderaFormsQuery\MySqlBuilder
-	 */
-	protected function MySqlBuilderFactory(): \calderawp\CalderaFormsQuery\MySqlBuilder
-	{
-		return new \calderawp\CalderaFormsQuery\MySqlBuilder();
-	}
-
-	/**
-	 * @return EntryQueries
-	 */
-	protected function entryQueriesFactory()
-	{
-		return new EntryQueries(
-			$this->entryGeneratorFactory(),
-			$this->entryValuesGeneratorFactory(),
-			new \wpdb()
-		);
-	}
+	use HasFactories;
 }
diff --git a/Tests/bootstrap-integration.php b/Tests/bootstrap-integration.php
index b8d92072b469dab7da458f6d0d339c04e83a4415..ba70ef1c15e807546bbe709c52f3753434122a78 100755
--- a/Tests/bootstrap-integration.php
+++ b/Tests/bootstrap-integration.php
@@ -18,7 +18,13 @@ require_once $_tests_dir . '/includes/functions.php';
 function _manually_load_plugin()
 {
 	require dirname(dirname(__FILE__)) . '/caldera-forms-query.php';
+	//Add Caldera Forms
 	require __DIR__ . '/plugins/caldera-forms/caldera-core.php';
+	//Add some Caldera Forms testing tools
+	require_once  __DIR__ .'/plugins/caldera-forms/tests/includes/traits/has-mock-form.php';
+	require_once  __DIR__ .'/plugins/caldera-forms/tests/includes/traits/has-data.php';
+	require_once  __DIR__ .'/plugins/caldera-forms/tests/includes/traits/imports-form.php';
+	require_once  __DIR__ .'/plugins/caldera-forms/tests/includes/traits/submits-contact-form.php';
 }
 tests_add_filter('muplugins_loaded', '_manually_load_plugin');
 
diff --git a/Tests/bootstrap.php b/Tests/bootstrap.php
index 6e9dc42650214eaa6dc2577be387cbe11177f23b..6a6615d0e579c11c7734892962aaf6784eb2f10c 100755
--- a/Tests/bootstrap.php
+++ b/Tests/bootstrap.php
@@ -31,8 +31,8 @@ if (! function_exists('__')) {
 		return translate($text, $domain);
 	}
 }
-//Mock WPDB (not using autoloader so it doesn't load during integration tests
-include_once __DIR__ . '/Mock/wpdb.php';
+
+
 //WordPress WPDB constants
 if ( ! defined( 'ARRAY_A')) {
 	define('OBJECT', 'OBJECT');
diff --git a/Tests/plugins/caldera-forms b/Tests/plugins/caldera-forms
index 3b0a81ff69ed4aaaaa92987c0fff4520e7252f25..c4c2d1db6042c82f2229c89ed7140c8b214c9c8e 160000
--- a/Tests/plugins/caldera-forms
+++ b/Tests/plugins/caldera-forms
@@ -1 +1 @@
-Subproject commit 3b0a81ff69ed4aaaaa92987c0fff4520e7252f25
+Subproject commit c4c2d1db6042c82f2229c89ed7140c8b214c9c8e
diff --git a/composer.json b/composer.json
index 3e7ae9fadab49ed079710f868d02110c3d6642ad..cec96b39e86836b7f5cd2087f5b7ac75c3905597 100644
--- a/composer.json
+++ b/composer.json
@@ -25,10 +25,9 @@
         }
     },
     "scripts" : {
-        "tests" : "composer fixes && composer sniffs && composer unit-tests && composer wp-tests",
+        "tests" : "composer unit-tests && composer wp-tests",
         "unit-tests": "phpunit --testsuite=unit",
         "wp-install": "bash ./bin/install-docker.sh",
-        "wp-start": "docker-compose up -d",
         "wp-tests": "docker-compose run --rm wordpress_phpunit phpunit --configuration phpunit-integration.xml.dist",
         "phpunit-v": "phpunit --version",
         "sniffs" : "phpcs src/ && phpcs Tests/",
@@ -46,7 +45,7 @@
         "phpunit/phpunit": "^7.0",
         "squizlabs/php_codesniffer": "^3.2",
         "jakub-onderka/php-parallel-lint": "^1.0",
-        "Desertsnowman/caldera-forms": "dev-develop",
+        "Desertsnowman/caldera-forms": "dev-feature/2404",
         "composer/installers": "~1.0"
     },
     "extra" : {
diff --git a/composer.lock b/composer.lock
index d5f6230433af7506f08fa4b54ea0a2fdbd2d3aa7..3a8a50c2469efb7854dcfa5762c05ebd4866665e 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "content-hash": "a6eee6d6f3062af42dc7b830f7971dac",
+    "content-hash": "90b8c6ac2ab8c558b28b1aea0f40cc18",
     "packages": [
         {
             "name": "nilportugues/sql-query-builder",
@@ -129,11 +129,11 @@
     "packages-dev": [
         {
             "name": "Desertsnowman/caldera-forms",
-            "version": "dev-develop",
+            "version": "dev-feature/2404",
             "source": {
                 "type": "git",
                 "url": "git@github.com:CalderaWP/Caldera-Forms.git",
-                "reference": "3b0a81ff69ed4aaaaa92987c0fff4520e7252f25"
+                "reference": "c4c2d1db6042c82f2229c89ed7140c8b214c9c8e"
             },
             "type": "wordpress-plugin",
             "license": [
@@ -153,7 +153,7 @@
                 "forms",
                 "wordpress"
             ],
-            "time": "2018-04-03T13:13:16+00:00"
+            "time": "2018-04-04T21:06:37+00:00"
         },
         {
             "name": "composer/installers",
diff --git a/src/Delete/DeleteQueryBuilder.php b/src/Delete/DeleteQueryBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..3f5d487452aeb533452be7dee54550aef42f1a81
--- /dev/null
+++ b/src/Delete/DeleteQueryBuilder.php
@@ -0,0 +1,37 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery\Delete;
+
+
+use calderawp\CalderaFormsQuery\QueryBuilder;
+use NilPortugues\Sql\QueryBuilder\Manipulation\Delete;
+
+abstract class DeleteQueryBuilder extends QueryBuilder implements DoesDeleteQuery
+{
+
+	/**
+	 * @var Delete
+	 */
+	protected $deleteQuery;
+
+	/**
+	 * @return Delete
+	 */
+	public function getDeleteQuery()
+	{
+		if( ! $this->deleteQuery ){
+			$this->deleteQuery = new Delete($this->getTableName());
+		}
+
+		return $this->deleteQuery;
+	}
+
+	/**
+	 * @return Delete
+	 */
+	public function getCurrentQuery()
+	{
+		return $this->getDeleteQuery();
+	}
+}
\ No newline at end of file
diff --git a/src/Delete/DoesDeleteQuery.php b/src/Delete/DoesDeleteQuery.php
new file mode 100644
index 0000000000000000000000000000000000000000..f01a333ea50f749e161ba8588d14fc92f53485fa
--- /dev/null
+++ b/src/Delete/DoesDeleteQuery.php
@@ -0,0 +1,24 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery\Delete;
+
+
+use NilPortugues\Sql\QueryBuilder\Manipulation\Delete;
+
+/**
+ * Interface DoesDeleteQuery
+ *
+ * Interface that delete query builders MUST implement.
+ */
+interface DoesDeleteQuery
+{
+
+	/**
+	 * Get current delete query
+	 *
+	 * @return Delete
+	 */
+	public function getCurrentQuery();
+
+}
\ No newline at end of file
diff --git a/src/Delete/Entry.php b/src/Delete/Entry.php
new file mode 100644
index 0000000000000000000000000000000000000000..1d550bfd4e6ec1891f20a413e6bfe72749ff9c8e
--- /dev/null
+++ b/src/Delete/Entry.php
@@ -0,0 +1,42 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery\Delete;
+
+
+class Entry extends DeleteQueryBuilder
+{
+
+	/**
+	 * Delete all entries with a specific form ID
+	 *
+	 * @param string $formId Form ID to delete entries of
+	 * @return $this
+	 */
+	public function deleteByFormId($formId)
+	{
+		return $this->is('form_id', $formId);
+	}
+
+	/**
+	 * Delete a specific entry by user ID
+	 *
+	 * @param $entryId
+	 * @return $this
+	 */
+	public function deleteByEntryId($entryId)
+	{
+		return $this->is('id', $entryId);
+	}
+
+	/**
+	 * Delete entries belonging to a specific user ID
+	 *
+	 * @param $userId
+	 * @return $this
+	 */
+	public function deleteByUserId($userId)
+	{
+		return $this->is('user_id', $userId);
+	}
+}
\ No newline at end of file
diff --git a/src/Delete/EntryValues.php b/src/Delete/EntryValues.php
new file mode 100644
index 0000000000000000000000000000000000000000..520753745e28464553ead93008b1a988617d9837
--- /dev/null
+++ b/src/Delete/EntryValues.php
@@ -0,0 +1,49 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery\Delete;
+
+
+class EntryValues extends DeleteQueryBuilder
+{
+
+	/**
+	 * Delete field by entry ID
+	 *
+	 * @param int $entryId Entry ID
+	 * @return $this
+	 */
+	public function deleteByEntryId($entryId)
+	{
+		$this
+			->getDeleteQuery()
+			->where()
+			->equals( 'entry_id', (int)$entryId )
+		;
+		return $this;
+	}
+
+	/**
+	 * Delete all field values with a value
+	 *
+	 * @param string $fieldSlug
+	 * @param string $fieldValue
+	 * @return $this
+	 */
+	public function deleteByFieldValue($fieldSlug, $fieldValue)
+	{
+		$this
+			->getDeleteQuery()
+			->where()
+			->equals( 'value', $fieldValue )
+
+		;
+
+		$this
+			->getDeleteQuery()
+			->where()
+			->equals( 'slug', $fieldSlug );
+		return $this;
+	}
+
+}
\ No newline at end of file
diff --git a/src/Escape.php b/src/Escape.php
new file mode 100644
index 0000000000000000000000000000000000000000..f09d0660bc58804b5bfb1b3bbddddc30e9929287
--- /dev/null
+++ b/src/Escape.php
@@ -0,0 +1,40 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery;
+
+/**
+ * Class Escape
+ *
+ * SQL Escape functions
+ */
+class Escape
+{
+
+	/**
+	 * Copy of WPDB::esc_like()
+	 *
+	 * First half of escaping for LIKE special characters % and _ before preparing for MySQL.
+	 *
+	 * Use this only before wpdb::prepare() or esc_sql().  Reversing the order is very bad for security.
+	 *
+	 * Example Prepared Statement:
+	 *
+	 *     $wild = '%';
+	 *     $find = 'only 43% of planets';
+	 *     $like = $wild . $wpdb->esc_like( $find ) . $wild;
+	 *     $sql  = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE %s", $like );
+	 *
+	 * Example Escape Chain:
+	 *
+	 *     $sql  = esc_sql( $wpdb->esc_like( $input ) );
+	 * @param string $text The raw text to be escaped. The input typed by the user should have no
+	 *                     extra or deleted slashes.
+	 * @return string Text in the form of a LIKE phrase. The output is not SQL safe. Call $wpdb::prepare()
+	 *                or real_escape next.
+	 */
+	public static function like( $text ) {
+		return addcslashes( $text, '_%\\' );
+	}
+
+}
\ No newline at end of file
diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..f4075a3e83bc55e42746621ca1b474083c595ed9
--- /dev/null
+++ b/src/QueryBuilder.php
@@ -0,0 +1,139 @@
+<?php
+
+
+namespace calderawp\CalderaFormsQuery;
+
+
+use calderawp\CalderaFormsQuery\Select\DoesSelectQuery;
+use NilPortugues\Sql\QueryBuilder\Manipulation\AbstractBaseQuery;
+
+abstract class QueryBuilder implements DoesQueries
+{
+	const ASC = 'ASC';
+	const DESC = 'DESC';
+
+	/**
+	 * @var MySqlBuilder
+	 */
+	private $builder;
+
+	/**
+	 * @var bool
+	 */
+	protected $isLike = false;
+
+	/**
+	 * @var string
+	 */
+	private $tableName;
+
+
+	/**
+	 * SelectQueryBuilder constructor.
+	 * @param MySqlBuilder $builder Query builder
+	 * @param string $tableName Name of table
+	 */
+	public function __construct(MySqlBuilder $builder, $tableName)
+	{
+		$this->builder = $builder;
+		$this->tableName = $tableName;
+	}
+
+	/**
+	 * @return AbstractBaseQuery
+	 */
+	abstract protected function getCurrentQuery();
+
+	/** @inheritdoc */
+	public function getTableName()
+	{
+		return $this->tableName;
+	}
+
+	/** @inheritdoc */
+	public function getBuilder()
+	{
+		return $this->builder;
+	}
+
+	/**
+	 * Add a where $column equals $value clause to query
+	 *
+	 * @param AbstractBaseQuery $queryBuilder
+	 * @param string $column
+	 * @param string $value
+	 * @return $this
+	 */
+	protected function addWhereEquals( AbstractBaseQuery $queryBuilder, $column, $value )
+	{
+		$queryBuilder
+			->where()
+			->equals($column, $value);
+		return $this;
+	}
+
+
+	/**
+	 * Replace all substitutions with actual values
+	 *
+	 * @param string $sql SQL query with substitutions
+	 * @return string
+	 */
+	protected function substituteValues($sql)
+	{
+		$values = $this->getBuilder()->getValues();
+		foreach ($values as $identifier => $value) {
+			$values[$identifier] = $this->surroundValue($value);
+		}
+		return str_replace(array_keys($values), array_values($values), $sql);
+	}
+
+	/**
+	 * @return string
+	 */
+	protected function getFirstDeliminator()
+	{
+		return $this->isLike ? "'%" : "'";
+	}
+
+	/**
+	 * @return string
+	 */
+	protected function getSecondDeliminator()
+	{
+		return $this->isLike ? "%'" : "'";	}
+
+	/**
+	 * Surround one value with quotes or %
+	 *
+	 * @param string $value Value to surround
+	 * @return string
+	 */
+	protected function surroundValue($value)
+	{
+		$value = "{$this->getFirstDeliminator()}$value{$this->getSecondDeliminator()}";
+		if( ! $this->isLike){
+			return $value;
+		}
+		return Escape::like( $value );
+	}
+
+
+	/**
+	 * Generate query for where column is value
+	 *
+	 * @param string $column
+	 * @param string $value
+	 * @return $this
+	 */
+	protected function is($column, $value)
+	{
+		return $this->addWhereEquals($this->getCurrentQuery(),$column, $value);
+	}
+
+	/** @inheritdoc */
+	public function getPreparedSql()
+	{
+		return $this->substituteValues($this->getBuilder()->write($this->getCurrentQuery()));
+	}
+}
\ No newline at end of file
diff --git a/src/Select/Entry.php b/src/Select/Entry.php
index 49b4027428d72128a0067eadc0502dd9be5c62d5..1a930b3e9b82453d07b4f8320683c7c5dcfb81d7 100644
--- a/src/Select/Entry.php
+++ b/src/Select/Entry.php
@@ -6,21 +6,15 @@ namespace calderawp\CalderaFormsQuery\Select;
 /**
  * Class Entry
  * @package calderawp\CalderaFormsQuery\Select
-
-`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-`form_id` varchar(18) NOT NULL DEFAULT '',
-`user_id` int(11) NOT NULL,
-`datestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
-`status` varchar(20) NOT NULL DEFAULT 'active',
  */
 class Entry extends SelectQueryBuilder
 {
 
 
 	/**
+	 * Get all entries for a specific form
 	 *
-	 *
-	 * @param $formId
+	 * @param string $formId Form Id
 	 * @return $this
 	 */
 	public function queryByFormsId($formId)
@@ -28,11 +22,23 @@ class Entry extends SelectQueryBuilder
 		return $this->is('form_id', $formId);
 	}
 
+	/**
+	 * Get entry by ID
+	 *
+	 * @param int $entryId Entry ID
+	 * @return $this
+	 */
 	public function queryByEntryId($entryId)
 	{
 		return $this->is('id', $entryId);
 	}
 
+	/**
+	 * Get all entries for a specific user
+	 *
+	 * @param int $userId
+	 * @return $this
+	 */
 	public function queryByUserId($userId)
 	{
 		return $this->is('user_id', $userId);
diff --git a/src/Select/SelectQueryBuilder.php b/src/Select/SelectQueryBuilder.php
index d76d098496196e543dcf0cbeed495ff13aba7bd8..c21ab94d841846e02d072183bbd6410a7b182a0d 100644
--- a/src/Select/SelectQueryBuilder.php
+++ b/src/Select/SelectQueryBuilder.php
@@ -5,72 +5,35 @@ namespace calderawp\CalderaFormsQuery\Select;
 
 use calderawp\CalderaFormsQuery\DoesQueries;
 use calderawp\CalderaFormsQuery\MySqlBuilder;
+use calderawp\CalderaFormsQuery\QueryBuilder;
+use NilPortugues\Sql\QueryBuilder\Manipulation\AbstractBaseQuery;
+use NilPortugues\Sql\QueryBuilder\Manipulation\Delete;
 use NilPortugues\Sql\QueryBuilder\Manipulation\Select;
 
-abstract class SelectQueryBuilder implements DoesQueries, DoesSelectQuery
+abstract class SelectQueryBuilder extends QueryBuilder implements  DoesSelectQuery
 {
-	const ASC = 'ASC';
-	const DESC = 'DESC';
-
-	/**
-	 * @var MySqlBuilder
-	 */
-	private $builder;
 
 	/**
 	 * @var Select
 	 */
-	private $query;
-
-	/**
-	 * @var bool
-	 */
-	protected $isLike = false;
-
-	/**
-	 * @var string
-	 */
-	private $tableName;
-
-
-	/**
-	 * SelectQueryBuilder constructor.
-	 * @param MySqlBuilder $builder Query builder
-	 * @param string $tableName Name of table
-	 */
-	public function __construct(MySqlBuilder $builder, $tableName)
-	{
-		$this->builder = $builder;
-		$this->tableName = $tableName;
-	}
-
-	/** @inheritdoc */
-	public function getTableName()
-	{
-		return $this->tableName;
-	}
-
-	/** @inheritdoc */
-	public function getBuilder()
-	{
-		return $this->builder;
-	}
-
+	private $selectQuery;
 
 	/** @inheritdoc */
 	public function getSelectQuery()
 	{
 
-		if (empty($this->query)) {
-			$this->query = new \NilPortugues\Sql\QueryBuilder\Manipulation\Select($this->getTableName());
+		if (empty($this->selectQuery)) {
+			$this->selectQuery = new \NilPortugues\Sql\QueryBuilder\Manipulation\Select($this->getTableName());
 		}
-		return $this->query;
+		return $this->selectQuery;
 	}
 
-	/** @inheritdoc */
-	public function getPreparedSql()
+	/**
+	 * @return Select
+	 */
+	protected function getCurrentQuery()
 	{
-		return $this->substituteValues($this->getBuilder()->write($this->getSelectQuery()));
+		return $this->getSelectQuery();
 	}
 
 	/**
@@ -81,57 +44,11 @@ abstract class SelectQueryBuilder implements DoesQueries, DoesSelectQuery
 	public function addOrderBy($column, $ascending = true)
 	{
 		$order = $ascending ? self::ASC : self::DESC;
-		$this->getSelectQuery()->orderBy($column, $order);
+		$this->getCurrentQuery()->orderBy($column, $order);
 		return $this;
 	}
 
-	/**
-	 * Generate query for where column is value
-	 *
-	 * @param string $column
-	 * @param string $value
-	 * @return $this
-	 */
-	protected function is($column, $value)
-	{
-		$this->getSelectQuery()
-			->where()
-			->equals($column, $value);
-		return $this;
-	}
 
 
-	/**
-	 * Replace all substitutions with actual values
-	 *
-	 * @param string $sql SQL query with substitutions
-	 * @return string
-	 */
-	protected function substituteValues($sql)
-	{
-		$values = $this->builder->getValues();
-		foreach ($values as $identifier => $value) {
-			$values[$identifier] = $this->surroundValue($value);
-		}
-		return str_replace(array_keys($values), array_values($values), $sql);
-	}
 
-	/**
-	 * @return string
-	 */
-	protected function getDeliminator()
-	{
-		return $this->isLike ? '%' : "'";
-	}
-
-	/**
-	 * Surround one value with quotes or %
-	 *
-	 * @param string $value Value to surround
-	 * @return string
-	 */
-	protected function surroundValue($value)
-	{
-		return "{$this->getDeliminator()}$value{$this->getDeliminator()}";
-	}
 }