diff --git tests/phpunit/tests/post/query.php tests/phpunit/tests/post/query.php
index 004e710..77db35b 100644
--- tests/phpunit/tests/post/query.php
+++ tests/phpunit/tests/post/query.php
@@ -332,37 +332,6 @@ class Tests_Post_Query extends WP_UnitTestCase {
 
 	}
 
-	/**
-	 * @ticket 20604
-	 */
-	function test_taxonomy_empty_or() {
-		// An empty tax query should return an empty array, not all posts.
-
-		$this->factory->post->create_many( 10 );
-
-		$query = new WP_Query( array(
-			'fields'	=> 'ids',
-			'tax_query' => array(
-			'relation' => 'OR',
-			array(
-				'taxonomy' => 'post_tag',
-				'field' => 'id',
-				'terms' => false,
-				'operator' => 'IN'
-			),
-			array(
-				'taxonomy' => 'category',
-				'field' => 'id',
-				'terms' => false,
-				'operator' => 'IN'
-			)
-			)
-		) );
-
-		$posts = $query->get_posts();
-		$this->assertEquals( 0 , count( $posts ) );
-	}
-
 	function test_meta_between_not_between() {
 		$post_id = $this->factory->post->create();
 		add_post_meta( $post_id, 'time', 500 );
@@ -543,7 +512,500 @@ class Tests_Post_Query extends WP_UnitTestCase {
 		$this->assertEqualSets( array( $post_id, $post_id3, $post_id4, $post_id5, $post_id6 ), $posts );
 	}
 
-	function test_taxonomy_include_children() {
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_single_query_single_term_field_slug() {
+		$t = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'foo',
+			'name' => 'Foo',
+		) );
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+
+		wp_set_post_terms( $p1, $t, 'category' );
+
+		$q = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( 'foo' ),
+					'field' => 'slug',
+				),
+			),
+		) );
+
+		$this->assertEquals( array( $p1 ), $q->posts );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_single_query_single_term_field_name() {
+		$t = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'foo',
+			'name' => 'Foo',
+		) );
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+
+		wp_set_post_terms( $p1, $t, 'category' );
+
+		$q = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( 'Foo' ),
+					'field' => 'name',
+				),
+			),
+		) );
+
+		$this->assertEquals( array( $p1 ), $q->posts );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_single_query_single_term_field_term_taxonomy_id() {
+		$t = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'foo',
+			'name' => 'Foo',
+		) );
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+
+		$tt_ids = wp_set_post_terms( $p1, $t, 'category' );
+
+		$q = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				array(
+					'taxonomy' => 'category',
+					'terms' => $tt_ids,
+					'field' => 'term_taxonomy_id',
+				),
+			),
+		) );
+
+		$this->assertEquals( array( $p1 ), $q->posts );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_single_query_single_term_field_term_id() {
+		$t = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'foo',
+			'name' => 'Foo',
+		) );
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+
+		wp_set_post_terms( $p1, $t, 'category' );
+
+		$q = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( $t ),
+					'field' => 'term_id',
+				),
+			),
+		) );
+
+		$this->assertEquals( array( $p1 ), $q->posts );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_single_query_single_term_operator_in() {
+		$t = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'foo',
+			'name' => 'Foo',
+		) );
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+
+		wp_set_post_terms( $p1, $t, 'category' );
+
+		$q = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( 'foo' ),
+					'field' => 'slug',
+					'operator' => 'IN',
+				),
+			),
+		) );
+
+		$this->assertEquals( array( $p1 ), $q->posts );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_single_query_single_term_operator_not_in() {
+		$t = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'foo',
+			'name' => 'Foo',
+		) );
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+
+		wp_set_post_terms( $p1, $t, 'category' );
+
+		$q = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( 'foo' ),
+					'field' => 'slug',
+					'operator' => 'NOT IN',
+				),
+			),
+		) );
+
+		$this->assertEquals( array( $p2 ), $q->posts );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_single_query_single_term_operator_and() {
+		$t = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'foo',
+			'name' => 'Foo',
+		) );
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+
+		wp_set_post_terms( $p1, $t, 'category' );
+
+		$q = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( 'foo' ),
+					'field' => 'slug',
+					'operator' => 'AND',
+				),
+			),
+		) );
+
+		$this->assertEquals( array( $p1 ), $q->posts );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_single_query_multiple_terms_operator_in() {
+		$t1 = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'foo',
+			'name' => 'Foo',
+		) );
+		$t2 = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'bar',
+			'name' => 'Bar',
+		) );
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+		$p3 = $this->factory->post->create();
+
+		wp_set_post_terms( $p1, $t1, 'category' );
+		wp_set_post_terms( $p2, $t2, 'category' );
+
+		$q = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( 'foo', 'bar' ),
+					'field' => 'slug',
+					'operator' => 'IN',
+				),
+			),
+		) );
+
+		$this->assertEquals( array( $p1, $p2 ), $q->posts );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_single_query_multiple_terms_operator_not_in() {
+		$t1 = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'foo',
+			'name' => 'Foo',
+		) );
+		$t2 = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'bar',
+			'name' => 'Bar',
+		) );
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+		$p3 = $this->factory->post->create();
+
+		wp_set_post_terms( $p1, $t1, 'category' );
+		wp_set_post_terms( $p2, $t2, 'category' );
+
+		$q = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( 'foo', 'bar' ),
+					'field' => 'slug',
+					'operator' => 'NOT IN',
+				),
+			),
+		) );
+
+		$this->assertEquals( array( $p3 ), $q->posts );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_single_query_multiple_terms_operator_and() {
+		$t1 = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'foo',
+			'name' => 'Foo',
+		) );
+		$t2 = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'bar',
+			'name' => 'Bar',
+		) );
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+		$p3 = $this->factory->post->create();
+
+		wp_set_object_terms( $p1, $t1, 'category' );
+		wp_set_object_terms( $p2, array( $t1, $t2 ), 'category' );
+
+		$q = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( 'foo', 'bar' ),
+					'field' => 'slug',
+					'operator' => 'AND',
+				),
+			),
+		) );
+
+		$this->assertEquals( array( $p2 ), $q->posts );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_multiple_queries_relation_and() {
+		$t1 = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'foo',
+			'name' => 'Foo',
+		) );
+		$t2 = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'bar',
+			'name' => 'Bar',
+		) );
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+		$p3 = $this->factory->post->create();
+
+		wp_set_object_terms( $p1, $t1, 'category' );
+		wp_set_object_terms( $p2, array( $t1, $t2 ), 'category' );
+
+		$q = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				'relation' => 'AND',
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( 'foo' ),
+					'field' => 'slug',
+				),
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( 'bar' ),
+					'field' => 'slug',
+				),
+			),
+		) );
+
+		$this->assertEquals( array( $p2 ), $q->posts );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_multiple_queries_relation_or() {
+		$t1 = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'foo',
+			'name' => 'Foo',
+		) );
+		$t2 = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'bar',
+			'name' => 'Bar',
+		) );
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+		$p3 = $this->factory->post->create();
+
+		wp_set_object_terms( $p1, $t1, 'category' );
+		wp_set_object_terms( $p2, array( $t1, $t2 ), 'category' );
+
+		$q = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				'relation' => 'OR',
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( 'foo' ),
+					'field' => 'slug',
+				),
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( 'bar' ),
+					'field' => 'slug',
+				),
+			),
+		) );
+
+		$this->assertEquals( array( $p1, $p2 ), $q->posts );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_multiple_queries_different_taxonomies() {
+		$t1 = $this->factory->term->create( array(
+			'taxonomy' => 'post_tag',
+			'slug' => 'foo',
+			'name' => 'Foo',
+		) );
+		$t2 = $this->factory->term->create( array(
+			'taxonomy' => 'category',
+			'slug' => 'bar',
+			'name' => 'Bar',
+		) );
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+		$p3 = $this->factory->post->create();
+
+		wp_set_object_terms( $p1, $t1, 'post_tag' );
+		wp_set_object_terms( $p2, $t2, 'category' );
+
+		$q = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				'relation' => 'OR',
+				array(
+					'taxonomy' => 'post_tag',
+					'terms' => array( 'foo' ),
+					'field' => 'slug',
+				),
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( 'bar' ),
+					'field' => 'slug',
+				),
+			),
+		) );
+
+		$this->assertEquals( array( $p1, $p2 ), $q->posts );
+	}
+
+	/**
+	 * @ticket 20604
+	 * @group taxonomy
+	 */
+	public function test_tax_query_empty_or() {
+		// An empty tax query should return an empty array, not all posts.
+
+		$this->factory->post->create_many( 10 );
+
+		$query = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_term_cache' => false,
+			'update_post_meta_cache' => false,
+			'tax_query' => array(
+				'relation' => 'OR',
+				array(
+					'taxonomy' => 'post_tag',
+					'field' => 'id',
+					'terms' => false,
+					'operator' => 'IN'
+				),
+				array(
+					'taxonomy' => 'category',
+					'field' => 'id',
+					'terms' => false,
+					'operator' => 'IN'
+				),
+			)
+		) );
+
+		$posts = $query->get_posts();
+		$this->assertEquals( 0 , count( $posts ) );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_include_children() {
 		$cat_a = $this->factory->term->create( array( 'taxonomy' => 'category', 'name' => 'Australia' ) );
 		$cat_b = $this->factory->term->create( array( 'taxonomy' => 'category', 'name' => 'Sydney', 'parent' => $cat_a ) );
 		$cat_c = $this->factory->term->create( array( 'taxonomy' => 'category', 'name' => 'East Syndney', 'parent' => $cat_b ) );
@@ -555,6 +1017,9 @@ class Tests_Post_Query extends WP_UnitTestCase {
 		$post_d = $this->factory->post->create( array( 'post_category' => array( $cat_d ) ) );
 
 		$posts = get_posts( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
 			'tax_query' => array(
 				array(
 					'taxonomy' => 'category',
@@ -567,6 +1032,9 @@ class Tests_Post_Query extends WP_UnitTestCase {
 		$this->assertEquals( 4 , count( $posts ) );
 
 		$posts = get_posts( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
 			'tax_query' => array(
 				array(
 					'taxonomy' => 'category',
@@ -580,6 +1048,9 @@ class Tests_Post_Query extends WP_UnitTestCase {
 		$this->assertEquals( 1 , count( $posts ) );
 
 		$posts = get_posts( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
 			'tax_query' => array(
 				array(
 					'taxonomy' => 'category',
@@ -592,6 +1063,9 @@ class Tests_Post_Query extends WP_UnitTestCase {
 		$this->assertEquals( 3 , count( $posts ) );
 
 		$posts = get_posts( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
 			'tax_query' => array(
 				array(
 					'taxonomy' => 'category',
@@ -605,6 +1079,9 @@ class Tests_Post_Query extends WP_UnitTestCase {
 		$this->assertEquals( 1 , count( $posts ) );
 
 		$posts = get_posts( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
 			'tax_query' => array(
 				array(
 					'taxonomy' => 'category',
@@ -617,6 +1094,9 @@ class Tests_Post_Query extends WP_UnitTestCase {
 		$this->assertEquals( 1 , count( $posts ) );
 
 		$posts = get_posts( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
 			'tax_query' => array(
 				array(
 					'taxonomy' => 'category',
@@ -631,6 +1111,260 @@ class Tests_Post_Query extends WP_UnitTestCase {
 	}
 
 	/**
+	 * @group taxonomy
+	 */
+	function test_category__and_var() {
+		$q = new WP_Query();
+
+		$term_id = $this->factory->category->create( array( 'slug' => 'woo', 'name' => 'WOO!' ) );
+		$term_id2 = $this->factory->category->create( array( 'slug' => 'hoo', 'name' => 'HOO!' ) );
+		$post_id = $this->factory->post->create();
+
+		wp_set_post_categories( $post_id, $term_id );
+
+		$posts = $q->query( array( 'category__and' => array( $term_id ) ) );
+
+		$this->assertEmpty( $q->get( 'category__and' ) );
+		$this->assertCount( 0, $q->get( 'category__and' ) );
+		$this->assertNotEmpty( $q->get( 'category__in' ) );
+		$this->assertCount( 1, $q->get( 'category__in' ) );
+
+		$this->assertNotEmpty( $posts );
+		$this->assertEquals( array( $post_id ), wp_list_pluck( $posts, 'ID' ) );
+
+		$posts2 = $q->query( array( 'category__and' => array( $term_id, $term_id2 ) ) );
+		$this->assertNotEmpty( $q->get( 'category__and' ) );
+		$this->assertCount( 2, $q->get( 'category__and' ) );
+		$this->assertEmpty( $q->get( 'category__in' ) );
+		$this->assertCount( 0, $q->get( 'category__in' ) );
+
+		$this->assertEmpty( $posts2 );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	public function test_tax_query_taxonomy_with_attachments() {
+		$q = new WP_Query();
+
+		register_taxonomy_for_object_type( 'post_tag', 'attachment:image' );
+		$tag_id = $this->factory->term->create( array( 'slug' => rand_str(), 'name' => rand_str() ) );
+		$image_id = $this->factory->attachment->create_object( 'image.jpg', 0, array(
+			'post_mime_type' => 'image/jpeg',
+			'post_type' => 'attachment'
+		) );
+		wp_set_object_terms( $image_id, $tag_id, 'post_tag' );
+
+		$posts = $q->query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'post_type' => 'attachment',
+			'post_status' => 'inherit',
+			'tax_query' => array(
+				array(
+					'taxonomy' => 'post_tag',
+					'field' => 'term_id',
+					'terms' => array( $tag_id )
+				)
+			)
+		) );
+
+		$this->assertEquals( array( $image_id ), $posts );
+	}
+
+	/**
+	 * @ticket 27193
+	 * @group taxonomy
+	 */
+	function test_cat_or_tag() {
+		$category1 = $this->factory->term->create( array( 'taxonomy' => 'category', 'name' => 'alpha' ) );
+		$category2 = $this->factory->term->create( array( 'taxonomy' => 'category', 'name' => 'beta' ) );
+
+		$tag1 = $this->factory->term->create( array( 'taxonomy' => 'post_tag', 'name' => 'gamma' ) );
+		$tag2 = $this->factory->term->create( array( 'taxonomy' => 'post_tag', 'name' => 'delta' ) );
+
+		$post_id1 = $this->factory->post->create( array( 'post_title' => 'alpha', 'post_category' => array( $category1 ) ) );
+		$terms1 = get_the_category( $post_id1 );
+		$this->assertEquals( array( get_category( $category1 ) ), $terms1 );
+
+		$post_id2 = $this->factory->post->create( array( 'post_title' => 'beta', 'post_category' => array( $category2 ) ) );
+		$terms2 = get_the_category( $post_id2 );
+		$this->assertEquals( array( get_category( $category2 ) ), $terms2 );
+
+		$post_id3 = $this->factory->post->create( array( 'post_title' => 'gamma', 'post_tag' => array( $tag1 ) ) );
+		$post_id4 = $this->factory->post->create( array( 'post_title' => 'delta', 'post_tag' => array( $tag2 ) ) );
+
+		$query = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				//'relation' => 'OR',
+				array(
+					'taxonomy' => 'category',
+					'field' => 'term_id',
+					'terms' => array( $category1, $category2 )
+				)
+			)
+		) );
+		$ids = $query->get_posts();
+		$this->assertEquals( array( $post_id1, $post_id2 ), $ids );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	function test_tax_query_no_taxonomy() {
+		$cat_id = $this->factory->category->create( array( 'name' => 'alpha' ) );
+		$this->factory->post->create( array( 'post_title' => 'alpha', 'post_category' => array( $cat_id ) ) );
+
+		$response1 = new WP_Query( array(
+			'tax_query' => array(
+				array( 'terms' => array( $cat_id ) )
+			)
+		) );
+		$this->assertEmpty( $response1->posts );
+
+		$response2 = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				array(
+					'taxonomy' => 'category',
+					'terms' => array( $cat_id )
+				)
+			)
+		) );
+		$this->assertNotEmpty( $response2->posts );
+
+		$term = get_category( $cat_id );
+		$response3 = new WP_Query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'tax_query' => array(
+				array(
+					'field' => 'term_taxonomy_id',
+					'terms' => array( $term->term_taxonomy_id )
+				)
+			)
+		) );
+		$this->assertNotEmpty( $response3->posts );
+	}
+
+	/**
+	 * @group taxonomy
+	 */
+	function test_term_taxonomy_id_field_no_taxonomy() {
+		$q = new WP_Query();
+
+		$posts = $this->factory->post->create_many( 5 );
+
+		$cats = $tags = array();
+
+		// need term_taxonomy_ids in addition to term_ids, so no factory
+		for ( $i = 0; $i < 5; $i++ ) {
+			$cats[$i] = wp_insert_term( 'category-' . $i , 'category' );
+			$tags[$i] = wp_insert_term( 'tag-' . $i, 'post_tag' );
+
+			// post 0 gets all terms
+			wp_set_object_terms( $posts[0], array( $cats[$i]['term_id'] ), 'category', true );
+			wp_set_object_terms( $posts[0], array( $tags[$i]['term_id'] ), 'post_tag', true );
+		}
+
+		wp_set_object_terms( $posts[1], array( $cats[0]['term_id'], $cats[2]['term_id'], $cats[4]['term_id'] ), 'category' );
+		wp_set_object_terms( $posts[1], array( $tags[0]['term_id'], $tags[2]['term_id'], $cats[4]['term_id'] ), 'post_tag' );
+
+		wp_set_object_terms( $posts[2], array( $cats[1]['term_id'], $cats[3]['term_id'] ), 'category' );
+		wp_set_object_terms( $posts[2], array( $tags[1]['term_id'], $tags[3]['term_id'] ), 'post_tag' );
+
+		wp_set_object_terms( $posts[3], array( $cats[0]['term_id'], $cats[2]['term_id'], $cats[4]['term_id'] ), 'category' );
+		wp_set_object_terms( $posts[3], array( $tags[1]['term_id'], $tags[3]['term_id'] ), 'post_tag' );
+
+		$results1 = $q->query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'orderby' => 'ID',
+			'order' => 'ASC',
+			'tax_query' => array(
+				'relation' => 'OR',
+				array(
+					'field' => 'term_taxonomy_id',
+					'terms' => array( $cats[0]['term_taxonomy_id'], $cats[2]['term_taxonomy_id'], $cats[4]['term_taxonomy_id'], $tags[0]['term_taxonomy_id'], $tags[2]['term_taxonomy_id'], $cats[4]['term_taxonomy_id'] ),
+					'operator' => 'AND',
+					'include_children' => false,
+				),
+				array(
+					'field' => 'term_taxonomy_id',
+					'terms' => array( $cats[1]['term_taxonomy_id'], $cats[3]['term_taxonomy_id'], $tags[1]['term_taxonomy_id'], $tags[3]['term_taxonomy_id'] ),
+					'operator' => 'AND',
+					'include_children' => false,
+				)
+			)
+		) );
+
+		$this->assertEquals( array( $posts[0], $posts[1], $posts[2] ), $results1, 'Relation: OR; Operator: AND' );
+
+		$results2 = $q->query( array(
+			'fields' => 'ids',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'orderby' => 'ID',
+			'order' => 'ASC',
+			'tax_query' => array(
+				'relation' => 'AND',
+				array(
+					'field' => 'term_taxonomy_id',
+					'terms' => array( $cats[0]['term_taxonomy_id'], $tags[0]['term_taxonomy_id'] ),
+					'operator' => 'IN',
+					'include_children' => false,
+				),
+				array(
+					'field' => 'term_taxonomy_id',
+					'terms' => array( $cats[3]['term_taxonomy_id'], $tags[3]['term_taxonomy_id'] ),
+					'operator' => 'IN',
+					'include_children' => false,
+				)
+			)
+		) );
+
+		$this->assertEquals( array( $posts[0], $posts[3] ), $results2, 'Relation: AND; Operator: IN' );
+	}
+
+	/**
+	 * @ticket 28099
+	 * @group taxonomy
+	 */
+	function test_empty_category__in() {
+		$cat_id = $this->factory->category->create();
+		$post_id = $this->factory->post->create();
+		wp_set_post_categories( $post_id, $cat_id );
+
+		$q1 = get_posts( array( 'category__in' => array( $cat_id ) ) );
+		$this->assertNotEmpty( $q1 );
+		$q2 = get_posts( array( 'category__in' => array() ) );
+		$this->assertNotEmpty( $q2 );
+
+		$tag = wp_insert_term( 'woo', 'post_tag' );
+		$tag_id = $tag['term_id'];
+		$slug = get_tag( $tag_id )->slug;
+		wp_set_post_tags( $post_id, $slug );
+
+		$q3 = get_posts( array( 'tag__in' => array( $tag_id ) ) );
+		$this->assertNotEmpty( $q3 );
+		$q4 = get_posts( array( 'tag__in' => array() ) );
+		$this->assertNotEmpty( $q4 );
+
+		$q5 = get_posts( array( 'tag_slug__in' => array( $slug ) ) );
+		$this->assertNotEmpty( $q5 );
+		$q6 = get_posts( array( 'tag_slug__in' => array() ) );
+		$this->assertNotEmpty( $q6 );
+	}
+
+	/**
 	 * @ticket 22448
 	 */
 	function test_the_posts_filter() {
@@ -831,4 +1565,4 @@ class Tests_Post_Query extends WP_UnitTestCase {
 			$q3->request
 		);
 	}
-}
\ No newline at end of file
+}
diff --git tests/phpunit/tests/term/query.php tests/phpunit/tests/term/query.php
index 0a3c724..5d839cb 100644
--- tests/phpunit/tests/term/query.php
+++ tests/phpunit/tests/term/query.php
@@ -6,229 +6,216 @@
 class Tests_Tax_Query extends WP_UnitTestCase {
 	protected $q;
 
-	function setUp() {
+	public function setUp() {
 		parent::setUp();
 		unset( $this->q );
 		$this->q = new WP_Query();
 	}
 
-	function test_category__and_var() {
-		$term_id = $this->factory->category->create( array( 'slug' => 'woo', 'name' => 'WOO!' ) );
-		$term_id2 = $this->factory->category->create( array( 'slug' => 'hoo', 'name' => 'HOO!' ) );
-		$post_id = $this->factory->post->create();
+	public function test_construct_with_relation_default() {
+		$tq = new WP_Tax_Query( array() );
+		$this->assertSame( 'AND', $tq->relation );
+	}
 
-		wp_set_post_categories( $post_id, $term_id );
+	public function test_construct_with_relation_or_lowercase() {
+		$tq = new WP_Tax_Query( array(
+			'relation' => 'or',
+		) );
+		$this->assertSame( 'OR', $tq->relation );
+	}
 
-		$posts = $this->q->query( array( 'category__and' => array( $term_id ) ) );
+	public function test_construct_with_relation_or_uppercase() {
+		$tq = new WP_Tax_Query( array(
+			'relation' => 'OR',
+		) );
+		$this->assertSame( 'OR', $tq->relation );
+	}
 
-		$this->assertEmpty( $this->q->get( 'category__and' ) );
-		$this->assertCount( 0, $this->q->get( 'category__and' ) );
-		$this->assertNotEmpty( $this->q->get( 'category__in' ) );
-		$this->assertCount( 1, $this->q->get( 'category__in' ) );
+	public function test_construct_with_relation_other() {
+		$tq = new WP_Tax_Query( array(
+			'relation' => 'foo',
+		) );
+		$this->assertSame( 'AND', $tq->relation );
+	}
 
-		$this->assertNotEmpty( $posts );
-		$this->assertEquals( array( $post_id ), wp_list_pluck( $posts, 'ID' ) );
+	public function test_construct_fill_missing_query_params() {
+		$tq = new WP_Tax_Query( array(
+			array(),
+		) );
 
-		$posts2 = $this->q->query( array( 'category__and' => array( $term_id, $term_id2 ) ) );
-		$this->assertNotEmpty( $this->q->get( 'category__and' ) );
-		$this->assertCount( 2, $this->q->get( 'category__and' ) );
-		$this->assertEmpty( $this->q->get( 'category__in' ) );
-		$this->assertCount( 0, $this->q->get( 'category__in' ) );
+		$expected = array(
+			'taxonomy' => '',
+			'terms' => array(),
+			'include_children' => true,
+			'field' => 'term_id',
+			'operator' => 'IN',
+		);
 
-		$this->assertEmpty( $posts2 );
+		$this->assertEquals( $expected, $tq->queries[0] );
 	}
 
-	function test_taxonomy_with_attachments() {
-		register_taxonomy_for_object_type( 'post_tag', 'attachment:image' );
-		$tag_id = $this->factory->term->create( array( 'slug' => rand_str(), 'name' => rand_str() ) );
-		$image_id = $this->factory->attachment->create_object( 'image.jpg', 0, array(
-			'post_mime_type' => 'image/jpeg',
-			'post_type' => 'attachment'
-		) );
-		wp_set_object_terms( $image_id, $tag_id, 'post_tag' );
-
-		$posts = $this->q->query( array(
-			'fields' => 'ids',
-			'post_type' => 'attachment',
-			'post_status' => 'inherit',
-			'tax_query' => array(
-				array(
-					'taxonomy' => 'post_tag',
-					'field' => 'term_id',
-					'terms' => array( $tag_id )
-				)
-			)
+	public function test_construct_fill_missing_query_params_merge_with_passed_values() {
+		$tq = new WP_Tax_Query( array(
+			array(
+				'taxonomy' => 'foo',
+				'include_children' => false,
+				'foo' => 'bar',
+			),
 		) );
 
-		$this->assertEquals( array( $image_id ), $posts );
+		$expected = array(
+			'taxonomy' => 'foo',
+			'terms' => array(),
+			'include_children' => false,
+			'field' => 'term_id',
+			'operator' => 'IN',
+			'foo' => 'bar',
+		);
+
+		$this->assertEquals( $expected, $tq->queries[0] );
 	}
 
-	/**
-	 * @ticket 27193
-	 */
-	function test_cat_or_tag() {
-		$category1 = $this->factory->term->create( array( 'taxonomy' => 'category', 'name' => 'alpha' ) );
-		$category2 = $this->factory->term->create( array( 'taxonomy' => 'category', 'name' => 'beta' ) );
+	public function test_construct_cast_terms_to_array() {
+		$tq = new WP_Tax_Query( array(
+			array(
+				'terms' => 'foo',
+			),
+		) );
 
-		$tag1 = $this->factory->term->create( array( 'taxonomy' => 'post_tag', 'name' => 'gamma' ) );
-		$tag2 = $this->factory->term->create( array( 'taxonomy' => 'post_tag', 'name' => 'delta' ) );
+		$this->assertEquals( array( 'foo', ), $tq->queries[0]['terms'] );
+	}
 
-		$post_id1 = $this->factory->post->create( array( 'post_title' => 'alpha', 'post_category' => array( $category1 ) ) );
-		$terms1 = get_the_category( $post_id1 );
-		$this->assertEquals( array( get_category( $category1 ) ), $terms1 );
+	public function test_transform_query_terms_empty() {
+		$tq = new WP_Tax_Query( array(
+			array(),
+		) );
+		$query = $tq->queries[0];
 
-		$post_id2 = $this->factory->post->create( array( 'post_title' => 'beta', 'post_category' => array( $category2 ) ) );
-		$terms2 = get_the_category( $post_id2 );
-		$this->assertEquals( array( get_category( $category2 ) ), $terms2 );
+		$tq->transform_query( $tq->queries[0], 'term_id' );
 
-		$post_id3 = $this->factory->post->create( array( 'post_title' => 'gamma', 'post_tag' => array( $tag1 ) ) );
-		$post_id4 = $this->factory->post->create( array( 'post_title' => 'delta', 'post_tag' => array( $tag2 ) ) );
+		$this->assertSame( $query, $tq->queries[0] );
+	}
 
-		$query = new WP_Query( array(
-			'fields' => 'ids',
-			'tax_query' => array(
-				//'relation' => 'OR',
-				array(
-					'taxonomy' => 'category',
-					'field' => 'term_id',
-					'terms' => array( $category1, $category2 )
-				)
-			)
+	public function test_transform_query_field_same_as_resulting_field() {
+		$tq = new WP_Tax_Query( array(
+			array(
+				'field' => 'term_id',
+			),
 		) );
-		$ids = $query->get_posts();
-		$this->assertEquals( array( $post_id1, $post_id2 ), $ids );
-	}
+		$query = $tq->queries[0];
 
-	function test_tax_query_no_taxonomy() {
-		$cat_id = $this->factory->category->create( array( 'name' => 'alpha' ) );
-		$this->factory->post->create( array( 'post_title' => 'alpha', 'post_category' => array( $cat_id ) ) );
+		$tq->transform_query( $tq->queries[0], 'term_id' );
 
-		$response1 = new WP_Query( array(
-			'tax_query' => array(
-				array( 'terms' => array( $cat_id ) )
-			)
-		) );
-		$this->assertEmpty( $response1->posts );
-
-		$response2 = new WP_Query( array(
-			'tax_query' => array(
-				array(
-					'taxonomy' => 'category',
-					'terms' => array( $cat_id )
-				)
-			)
+		$this->assertSame( $query, $tq->queries[0] );
+	}
+
+	public function test_transform_query_resulting_field_sanitized() {
+		$t1 = $this->factory->category->create( array( 'slug' => 'foo', ) );
+		$t2 = $this->factory->category->create( array( 'slug' => 'bar', ) );
+		$p = $this->factory->post->create();
+		wp_set_post_categories( $p, $t1 );
+
+		$tq1 = new WP_Tax_Query( array(
+			array(
+				'terms' => array( 'foo' ),
+				'field' => 'slug',
+			),
 		) );
-		$this->assertNotEmpty( $response2->posts );
-
-		$term = get_category( $cat_id );
-		$response3 = new WP_Query( array(
-			'tax_query' => array(
-				array(
-					'field' => 'term_taxonomy_id',
-					'terms' => array( $term->term_taxonomy_id )
-				)
-			)
+		$tq1->transform_query( $tq1->queries[0], 'term_taxonomy_id' );
+
+		$tq2 = new WP_Tax_Query( array(
+			array(
+				'terms' => array( 'foo' ),
+				'field' => 'slug',
+			),
 		) );
-		$this->assertNotEmpty( $response3->posts );
-	}
-
-	function test_term_taxonomy_id_field_no_taxonomy() {
-		$posts = $this->factory->post->create_many( 5 );
-
-		$cats = $tags = array();
-
-		// need term_taxonomy_ids in addition to term_ids, so no factory
-		for ( $i = 0; $i < 5; $i++ ) {
-			$cats[$i] = wp_insert_term( 'category-' . $i , 'category' );
-			$tags[$i] = wp_insert_term( 'tag-' . $i, 'post_tag' );
-
-			// post 0 gets all terms
-			wp_set_object_terms( $posts[0], array( $cats[$i]['term_id'] ), 'category', true );
-			wp_set_object_terms( $posts[0], array( $tags[$i]['term_id'] ), 'post_tag', true );
-		}
-
-		wp_set_object_terms( $posts[1], array( $cats[0]['term_id'], $cats[2]['term_id'], $cats[4]['term_id'] ), 'category' );
-		wp_set_object_terms( $posts[1], array( $tags[0]['term_id'], $tags[2]['term_id'], $cats[4]['term_id'] ), 'post_tag' );
-
-		wp_set_object_terms( $posts[2], array( $cats[1]['term_id'], $cats[3]['term_id'] ), 'category' );
-		wp_set_object_terms( $posts[2], array( $tags[1]['term_id'], $tags[3]['term_id'] ), 'post_tag' );
-
-		wp_set_object_terms( $posts[3], array( $cats[0]['term_id'], $cats[2]['term_id'], $cats[4]['term_id'] ), 'category' );
-		wp_set_object_terms( $posts[3], array( $tags[1]['term_id'], $tags[3]['term_id'] ), 'post_tag' );
-
-		$results1 = $this->q->query( array(
-			'fields' => 'ids',
-			'orderby' => 'ID',
-			'order' => 'ASC',
-			'tax_query' => array(
-				'relation' => 'OR',
-				array(
-					'field' => 'term_taxonomy_id',
-					'terms' => array( $cats[0]['term_taxonomy_id'], $cats[2]['term_taxonomy_id'], $cats[4]['term_taxonomy_id'], $tags[0]['term_taxonomy_id'], $tags[2]['term_taxonomy_id'], $cats[4]['term_taxonomy_id'] ),
-					'operator' => 'AND',
-					'include_children' => false,
-				),
-				array(
-					'field' => 'term_taxonomy_id',
-					'terms' => array( $cats[1]['term_taxonomy_id'], $cats[3]['term_taxonomy_id'], $tags[1]['term_taxonomy_id'], $tags[3]['term_taxonomy_id'] ),
-					'operator' => 'AND',
-					'include_children' => false,
-				)
-			)
+		$tq2->transform_query( $tq2->queries[0], 'TERM_ ta%xonomy_id' );
+
+		$this->assertSame( $tq1->queries[0], $tq2->queries[0] );
+	}
+
+	public function test_transform_query_field_slug() {
+		$t1 = $this->factory->category->create( array( 'slug' => 'foo', ) );
+		$p = $this->factory->post->create();
+		$tt_ids = wp_set_post_categories( $p, $t1 );
+
+		$tq = new WP_Tax_Query( array(
+			array(
+				'taxonomy' => 'category',
+				'terms' => array( 'foo' ),
+				'field' => 'slug',
+			),
 		) );
+		$tq->transform_query( $tq->queries[0], 'term_taxonomy_id' );
 
-		$this->assertEquals( array( $posts[0], $posts[1], $posts[2] ), $results1, 'Relation: OR; Operator: AND' );
-
-		$results2 = $this->q->query( array(
-			'fields' => 'ids',
-			'orderby' => 'ID',
-			'order' => 'ASC',
-			'tax_query' => array(
-				'relation' => 'AND',
-				array(
-					'field' => 'term_taxonomy_id',
-					'terms' => array( $cats[0]['term_taxonomy_id'], $tags[0]['term_taxonomy_id'] ),
-					'operator' => 'IN',
-					'include_children' => false,
-				),
-				array(
-					'field' => 'term_taxonomy_id',
-					'terms' => array( $cats[3]['term_taxonomy_id'], $tags[3]['term_taxonomy_id'] ),
-					'operator' => 'IN',
-					'include_children' => false,
-				)
-			)
+		$this->assertSame( $tt_ids, $tq->queries[0]['terms'] );
+		$this->assertSame( 'term_taxonomy_id', $tq->queries[0]['field'] );
+	}
+
+	public function test_transform_query_field_name() {
+		$t1 = $this->factory->category->create( array( 'slug' => 'foo', 'name' => 'Foo', ) );
+		$p = $this->factory->post->create();
+		$tt_ids = wp_set_post_categories( $p, $t1 );
+
+		$tq = new WP_Tax_Query( array(
+			array(
+				'taxonomy' => 'category',
+				'terms' => array( 'Foo' ),
+				'field' => 'name',
+			),
 		) );
+		$tq->transform_query( $tq->queries[0], 'term_taxonomy_id' );
 
-		$this->assertEquals( array( $posts[0], $posts[3] ), $results2, 'Relation: AND; Operator: IN' );
+		$this->assertSame( $tt_ids, $tq->queries[0]['terms'] );
+		$this->assertSame( 'term_taxonomy_id', $tq->queries[0]['field'] );
 	}
 
-	/**
-	 * @ticket 28099
-	 */
-	function test_empty__in() {
-		$cat_id = $this->factory->category->create();
-		$post_id = $this->factory->post->create();
-		wp_set_post_categories( $post_id, $cat_id );
+	public function test_transform_query_field_term_taxonomy_id() {
+		$t1 = $this->factory->category->create( array( 'slug' => 'foo', 'name' => 'Foo', ) );
+		$p = $this->factory->post->create();
+		$tt_ids = wp_set_post_categories( $p, $t1 );
+
+		$tq = new WP_Tax_Query( array(
+			array(
+				'taxonomy' => 'category',
+				'terms' => $tt_ids,
+				'field' => 'term_taxonomy_id',
+			),
+		) );
+		$tq->transform_query( $tq->queries[0], 'term_id' );
 
-		$q1 = get_posts( array( 'category__in' => array( $cat_id ) ) );
-		$this->assertNotEmpty( $q1 );
-		$q2 = get_posts( array( 'category__in' => array() ) );
-		$this->assertNotEmpty( $q2 );
+		$this->assertEquals( array( $t1 ), $tq->queries[0]['terms'] );
+		$this->assertSame( 'term_id', $tq->queries[0]['field'] );
+	}
 
-		$tag = wp_insert_term( 'woo', 'post_tag' );
-		$tag_id = $tag['term_id'];
-		$slug = get_tag( $tag_id )->slug;
-		wp_set_post_tags( $post_id, $slug );
+	public function test_transform_query_field_term_taxonomy_default() {
+		$t1 = $this->factory->category->create( array( 'slug' => 'foo', 'name' => 'Foo', ) );
+		$p = $this->factory->post->create();
+		$tt_ids = wp_set_post_categories( $p, $t1 );
+
+		$tq = new WP_Tax_Query( array(
+			array(
+				'taxonomy' => 'category',
+				'terms' => array( $t1 ),
+				'field' => 'foo', // Anything defaults to term_id
+			),
+		) );
+		$tq->transform_query( $tq->queries[0], 'term_taxonomy_id' );
 
-		$q3 = get_posts( array( 'tag__in' => array( $tag_id ) ) );
-		$this->assertNotEmpty( $q3 );
-		$q4 = get_posts( array( 'tag__in' => array() ) );
-		$this->assertNotEmpty( $q4 );
+		$this->assertEquals( $tt_ids, $tq->queries[0]['terms'] );
+		$this->assertSame( 'term_taxonomy_id', $tq->queries[0]['field'] );
+	}
+
+	public function test_transform_query_nonexistent_terms() {
+		$tq = new WP_Tax_Query( array(
+			array(
+				'terms' => array( 'foo' ),
+				'field' => 'slug',
+				'operator' => 'AND',
+			),
+		) );
+		$tq->transform_query( $tq->queries[0], 'term_taxonomy_id' );
 
-		$q5 = get_posts( array( 'tag_slug__in' => array( $slug ) ) );
-		$this->assertNotEmpty( $q5 );
-		$q6 = get_posts( array( 'tag_slug__in' => array() ) );
-		$this->assertNotEmpty( $q6 );
+		$this->assertTrue( is_wp_error( $tq->queries[0] ) );
 	}
 }
