diff --git a/tests/phpunit/includes/testcase.php b/tests/phpunit/includes/testcase.php
index 0528cff..b06fffe 100644
--- a/tests/phpunit/includes/testcase.php
+++ b/tests/phpunit/includes/testcase.php
@@ -184,8 +184,10 @@ class WP_UnitTestCase extends PHPUnit_Framework_TestCase {
 	 * it has a chance to do so.
 	 */
 	protected function reset_post_types() {
-		foreach ( get_post_types() as $pt ) {
-			_unregister_post_type( $pt );
+		foreach ( get_post_types( array(), 'objects' ) as $pt ) {
+			if ( empty( $pt->tests_no_auto_unregister ) ) {
+				_unregister_post_type( $pt->name );
+			}
 		}
 		create_initial_post_types();
 	}
diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php
index 9de7d88..99de8bd 100644
--- a/tests/phpunit/tests/rest-api/rest-comments-controller.php
+++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php
@@ -76,7 +76,9 @@ class WP_Test_REST_Comments_Controller extends WP_Test_REST_Controller_Testcase
 	}
 
 	public static function wpTearDownAfterClass() {
+		self::delete_user( self::$superadmin_id );
 		self::delete_user( self::$admin_id );
+		self::delete_user( self::$editor_id );
 		self::delete_user( self::$subscriber_id );
 		self::delete_user( self::$author_id );
 
diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php
index 67d4b0e..a026b8c 100644
--- a/tests/phpunit/tests/rest-api/rest-posts-controller.php
+++ b/tests/phpunit/tests/rest-api/rest-posts-controller.php
@@ -57,6 +57,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
 
 		wp_delete_post( self::$post_id, true );
 
+		self::delete_user( self::$superadmin_id );
 		self::delete_user( self::$editor_id );
 		self::delete_user( self::$author_id );
 		self::delete_user( self::$contributor_id );
diff --git a/tests/phpunit/tests/rest-api/rest-tags-controller.php b/tests/phpunit/tests/rest-api/rest-tags-controller.php
index bdca9cb..cb81b17 100644
--- a/tests/phpunit/tests/rest-api/rest-tags-controller.php
+++ b/tests/phpunit/tests/rest-api/rest-tags-controller.php
@@ -35,7 +35,9 @@ class WP_Test_REST_Tags_Controller extends WP_Test_REST_Controller_Testcase {
 	}
 
 	public static function wpTearDownAfterClass() {
+		self::delete_user( self::$superadmin );
 		self::delete_user( self::$administrator );
+		self::delete_user( self::$editor );
 		self::delete_user( self::$subscriber );
 	}
 
diff --git a/tests/phpunit/tests/rest-api/rest-users-controller.php b/tests/phpunit/tests/rest-api/rest-users-controller.php
index 2f17495..0d59281 100644
--- a/tests/phpunit/tests/rest-api/rest-users-controller.php
+++ b/tests/phpunit/tests/rest-api/rest-users-controller.php
@@ -13,9 +13,9 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
 	protected static $superadmin;
 	protected static $user;
 	protected static $editor;
-	protected static $editor2;
-	protected static $secret_editor;
-	protected static $secret_editor2;
+	protected static $draft_editor;
+	protected static $authors = array();
+	protected static $posts = array();
 	protected static $site;
 
 	public static function wpSetUpBeforeClass( $factory ) {
@@ -30,17 +30,38 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
 			'role'       => 'editor',
 			'user_email' => 'editor@example.com',
 		) );
-		self::$editor2 = $factory->user->create( array(
+		self::$draft_editor = $factory->user->create( array(
 			'role'       => 'editor',
-			'user_email' => 'editor2@example.com',
+			'user_email' => 'draft-editor@example.com',
 		) );
-		self::$secret_editor = $factory->user->create( array(
-			'role'       => 'editor',
-			'user_email' => 'secret_editor@example.com',
+
+		foreach ( array( true, false ) as $show_in_rest ) {
+			foreach ( array( true, false ) as $public ) {
+				$post_type_name = 'r_' . json_encode( $show_in_rest ) . '_p_' . json_encode( $public );
+				register_post_type( $post_type_name, array(
+					'public'                   => $public,
+					'show_in_rest'             => $show_in_rest,
+					'tests_no_auto_unregister' => true,
+				) );
+				self::$authors[ $post_type_name ] = $factory->user->create( array(
+					'role'       => 'editor',
+					'user_email' => 'author_' . $post_type_name . '@example.com',
+				) );
+				self::$posts[ $post_type_name ] = $factory->post->create( array(
+					'post_type'   => $post_type_name,
+					'post_author' => self::$authors[ $post_type_name ],
+				) );
+			}
+		}
+
+		self::$posts['post'] = $factory->post->create( array(
+			'post_type'   => 'post',
+			'post_author' => self::$editor,
 		) );
-		self::$secret_editor2 = $factory->user->create( array(
-			'role'       => 'editor',
-			'user_email' => 'secret_editor2@example.com',
+		self::$posts['r_true_p_true_DRAFT'] = $factory->post->create( array(
+			'post_type'   => 'r_true_p_true',
+			'post_author' => self::$draft_editor,
+			'post_status' => 'draft',
 		) );
 
 		if ( is_multisite() ) {
@@ -52,9 +73,18 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
 	public static function wpTearDownAfterClass() {
 		self::delete_user( self::$user );
 		self::delete_user( self::$editor );
-		self::delete_user( self::$editor2 );
-		self::delete_user( self::$secret_editor );
-		self::delete_user( self::$secret_editor2 );
+		self::delete_user( self::$draft_editor );
+
+		foreach ( self::$posts as $post ) {
+			wp_delete_post( $post, true );
+		}
+		foreach ( self::$authors as $author ) {
+			self::delete_user( $author );
+		}
+		_unregister_post_type( 'r_true_p_true' );
+		_unregister_post_type( 'r_true_p_false' );
+		_unregister_post_type( 'r_false_p_true' );
+		_unregister_post_type( 'r_false_p_false' );
 
 		if ( is_multisite() ) {
 			wpmu_delete_blog( self::$site, true );
@@ -66,12 +96,6 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
 	 */
 	public function setUp() {
 		parent::setUp();
-
-		register_post_type( 'rest_public', array( 'public' => true, 'show_in_rest' => true ) );
-		register_post_type( 'secret_public', array( 'public' => true, 'show_in_rest' => false ) );
-		register_post_type( 'secret_hidden', array( 'public' => false, 'show_in_rest' => false ) );
-		register_post_type( 'rest_hidden', array( 'public' => false, 'show_in_rest' => true ) );
-
 		$this->endpoint = new WP_REST_Users_Controller();
 	}
 
@@ -169,36 +193,14 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
 	}
 
 	public function test_get_items_unauthenticated_includes_authors_of_post_types_shown_in_rest() {
-		$created_posts = array();
-		$created_posts[] = $this->factory->post->create( array(
-			'post_author' => self::$user,
-			'post_status' => 'publish',
-		) );
-		// Expose authors if show_in_rest is true, even if the post_type is not public.
-		$created_posts[] = $this->factory->post->create( array(
-			'post_type' => 'rest_hidden',
-			'post_author' => self::$editor,
-			'post_status' => 'publish',
-		) );
-		$created_posts[] = $this->factory->post->create( array(
-			'post_type' => 'rest_public',
-			'post_author' => self::$editor2,
-			'post_status' => 'publish',
-		) );
-		$created_posts[] = $this->factory->post->create( array(
-			'post_type' => 'rest_public',
-			'post_author' => self::$secret_editor,
-			'post_status' => 'draft',
-		) );
-
 		$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
 		$response = $this->server->dispatch( $request );
 		$users = $response->get_data();
 
-		$public_post_types = array_values( get_post_types( array( 'show_in_rest' => true ), 'names' ) );
+		$rest_post_types = array_values( get_post_types( array( 'show_in_rest' => true ), 'names' ) );
 
 		foreach ( $users as $user ) {
-			$this->assertTrue( count_user_posts( $user['id'], $public_post_types ) > 0 );
+			$this->assertTrue( count_user_posts( $user['id'], $rest_post_types ) > 0 );
 
 			// Ensure we don't expose non-public data.
 			$this->assertArrayNotHasKey( 'capabilities', $user );
@@ -213,55 +215,45 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
 			$this->assertArrayNotHasKey( 'locale', $user );
 		}
 
-		$this->assertTrue( in_array( self::$user, wp_list_pluck( $users, 'id' ), true ) );
-		$this->assertTrue( in_array( self::$editor, wp_list_pluck( $users, 'id' ), true ) );
-		$this->assertTrue( in_array( self::$editor2, wp_list_pluck( $users, 'id' ), true ) );
-
-		// Do not include authors of unpublished posts.
-		$this->assertFalse( in_array( self::$secret_editor, wp_list_pluck( $users, 'id' ), true ) );
+		$user_ids = wp_list_pluck( $users, 'id' );
 
-		foreach ( $created_posts as $post_id ) {
-			wp_delete_post( $post_id, true );
-		}
+		$this->assertTrue( in_array( self::$editor                   , $user_ids, true ) );
+		$this->assertTrue( in_array( self::$authors['r_true_p_true'] , $user_ids, true ) );
+		$this->assertTrue( in_array( self::$authors['r_true_p_false'], $user_ids, true ) );
+		$this->assertCount( 3, $user_ids );
 	}
 
 	public function test_get_items_unauthenticated_does_not_include_authors_of_post_types_not_shown_in_rest() {
-		$created_posts = array();
-		$created_posts[] = $this->factory->post->create( array(
-			'post_type' => 'secret_hidden',
-			'post_author' => self::$secret_editor,
-			'post_status' => 'publish',
-		) );
-		$created_posts[] = $this->factory->post->create( array(
-			'post_type' => 'secret_public',
-			'post_author' => self::$secret_editor2,
-			'post_status' => 'publish',
-		) );
-
 		$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
 		$response = $this->server->dispatch( $request );
-		$data = $response->get_data();
+		$users = $response->get_data();
+		$user_ids = wp_list_pluck( $users, 'id' );
 
-		$this->assertFalse( in_array( self::$secret_editor, wp_list_pluck( $data, 'id' ), true ) );
-		$this->assertFalse( in_array( self::$secret_editor2, wp_list_pluck( $data, 'id' ), true ) );
+		$this->assertFalse( in_array( self::$authors['r_false_p_true'] , $user_ids, true ) );
+		$this->assertFalse( in_array( self::$authors['r_false_p_false'], $user_ids, true ) );
+	}
 
-		foreach ( $created_posts as $post_id ) {
-			wp_delete_post( $post_id, true );
-		}
+	public function test_get_items_unauthenticated_does_not_include_users_without_published_posts() {
+		$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
+		$response = $this->server->dispatch( $request );
+		$users = $response->get_data();
+		$user_ids = wp_list_pluck( $users, 'id' );
+
+		$this->assertFalse( in_array( self::$draft_editor, $user_ids, true ) );
+		$this->assertFalse( in_array( self::$user        , $user_ids, true ) );
 	}
 
 	public function test_get_items_pagination_headers() {
 		wp_set_current_user( self::$user );
-		// Start of the index, including the six existing users.
 		for ( $i = 0; $i < 44; $i++ ) {
 			$this->factory->user->create( array(
-				'name'   => "User {$i}",
-				) );
+				'name' => "User {$i}",
+			) );
 		}
 		$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
 		$response = $this->server->dispatch( $request );
 		$headers = $response->get_headers();
-		$this->assertEquals( 51, $headers['X-WP-Total'] );
+		$this->assertEquals( 53, $headers['X-WP-Total'] );
 		$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
 		$next_link = add_query_arg( array(
 			'page'    => 2,
@@ -276,7 +268,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
 		$request->set_param( 'page', 3 );
 		$response = $this->server->dispatch( $request );
 		$headers = $response->get_headers();
-		$this->assertEquals( 52, $headers['X-WP-Total'] );
+		$this->assertEquals( 54, $headers['X-WP-Total'] );
 		$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
 		$prev_link = add_query_arg( array(
 			'page'    => 2,
@@ -291,7 +283,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
 		$request->set_param( 'page', 6 );
 		$response = $this->server->dispatch( $request );
 		$headers = $response->get_headers();
-		$this->assertEquals( 52, $headers['X-WP-Total'] );
+		$this->assertEquals( 54, $headers['X-WP-Total'] );
 		$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
 		$prev_link = add_query_arg( array(
 			'page'    => 5,
@@ -303,7 +295,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
 		$request->set_param( 'page', 8 );
 		$response = $this->server->dispatch( $request );
 		$headers = $response->get_headers();
-		$this->assertEquals( 52, $headers['X-WP-Total'] );
+		$this->assertEquals( 54, $headers['X-WP-Total'] );
 		$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
 		$prev_link = add_query_arg( array(
 			'page'    => 6,
@@ -474,12 +466,12 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
 
 	public function test_get_items_offset() {
 		wp_set_current_user( self::$user );
-		// 5 users created in __construct(), plus default user.
+		// 7 users created in wpSetUpBeforeClass(), plus default user.
 		$this->factory->user->create();
 		$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
 		$request->set_param( 'offset', 1 );
 		$response = $this->server->dispatch( $request );
-		$this->assertCount( 7, $response->get_data() );
+		$this->assertCount( 9, $response->get_data() );
 		// 'offset' works with 'per_page'
 		$request->set_param( 'per_page', 2 );
 		$response = $this->server->dispatch( $request );
@@ -530,6 +522,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
 		$id1 = $this->factory->user->create();
 		$id2 = $this->factory->user->create();
 		$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
+		$request->set_param( 'per_page', 20 ); // there are >10 users at this point
 		$response = $this->server->dispatch( $request );
 		$data = $response->get_data();
 		$this->assertTrue( in_array( $id1, wp_list_pluck( $data, 'id' ), true ) );
@@ -688,15 +681,63 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
 		$this->assertEquals( $data['extra_capabilities'], new stdClass() );
 	}
 
-	public function test_get_item_without_permission() {
+	public function test_cannot_get_item_without_permission() {
 		wp_set_current_user( self::$editor );
-
 		$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$user ) );
 		$response = $this->server->dispatch( $request );
+		$this->assertErrorResponse( 'rest_user_cannot_view', $response, 403 );
+	}
+
+	public function test_can_get_item_author_of_rest_true_public_true_unauthenticated() {
+		$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$authors['r_true_p_true'] ) );
+		$response = $this->server->dispatch( $request );
+		$this->assertEquals( 200, $response->get_status() );
+	}
 
+	public function test_can_get_item_author_of_rest_true_public_true_authenticated() {
+		wp_set_current_user( self::$editor );
+		$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$authors['r_true_p_true'] ) );
+		$response = $this->server->dispatch( $request );
+		$this->assertEquals( 200, $response->get_status() );
+	}
+
+	public function test_can_get_item_author_of_rest_true_public_false() {
+		$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$authors['r_true_p_false'] ) );
+		$response = $this->server->dispatch( $request );
+		$this->assertEquals( 200, $response->get_status() );
+	}
+
+	public function test_cannot_get_item_author_of_rest_false_public_true_unauthenticated() {
+		$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$authors['r_false_p_true'] ) );
+		$response = $this->server->dispatch( $request );
+		$this->assertErrorResponse( 'rest_user_cannot_view', $response, 401 );
+	}
+
+	public function test_cannot_get_item_author_of_rest_false_public_true_without_permission() {
+		wp_set_current_user( self::$editor );
+		$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$authors['r_false_p_true'] ) );
+		$response = $this->server->dispatch( $request );
 		$this->assertErrorResponse( 'rest_user_cannot_view', $response, 403 );
 	}
 
+	public function test_cannot_get_item_author_of_rest_false_public_false() {
+		$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$authors['r_false_p_false'] ) );
+		$response = $this->server->dispatch( $request );
+		$this->assertErrorResponse( 'rest_user_cannot_view', $response, 401 );
+	}
+
+	public function test_can_get_item_author_of_post() {
+		$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$editor ) );
+		$response = $this->server->dispatch( $request );
+		$this->assertEquals( 200, $response->get_status() );
+	}
+
+	public function test_cannot_get_item_author_of_draft() {
+		$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$draft_editor ) );
+		$response = $this->server->dispatch( $request );
+		$this->assertErrorResponse( 'rest_user_cannot_view', $response, 401 );
+	}
+
 	public function test_get_item_published_author_post() {
 		$this->author_id = $this->factory->user->create( array(
 			'role' => 'author',
@@ -2166,11 +2207,6 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
 	}
 
 	public function tearDown() {
-		_unregister_post_type( 'rest_public' );
-		_unregister_post_type( 'secret_public' );
-		_unregister_post_type( 'secret_hidden' );
-		_unregister_post_type( 'rest_hidden' );
-
 		parent::tearDown();
 	}
 
