diff --git src/wp-admin/edit-form-advanced.php src/wp-admin/edit-form-advanced.php
index 75c3cef..0a1f886 100644
--- src/wp-admin/edit-form-advanced.php
+++ src/wp-admin/edit-form-advanced.php
@@ -259,8 +259,9 @@ foreach ( get_object_taxonomies( $post ) as $tax_name ) {
 	add_meta_box( $tax_meta_box_id, $label, $taxonomy->meta_box_cb, null, 'side', 'core', array( 'taxonomy' => $tax_name ) );
 }
 
-if ( post_type_supports($post_type, 'page-attributes') )
-	add_meta_box('pageparentdiv', 'page' == $post_type ? __('Page Attributes') : __('Attributes'), 'page_attributes_meta_box', null, 'side', 'core');
+if ( post_type_supports( $post_type, 'page-attributes' ) ) {
+	add_meta_box( 'pageparentdiv', $post_type_object->labels->attributes, 'page_attributes_meta_box', null, 'side', 'core' );
+}
 
 if ( $thumbnail_support && current_user_can( 'upload_files' ) )
 	add_meta_box('postimagediv', esc_html( $post_type_object->labels->featured_image ), 'post_thumbnail_meta_box', null, 'side', 'low');
diff --git src/wp-admin/includes/class-wp-posts-list-table.php src/wp-admin/includes/class-wp-posts-list-table.php
index 7ef790e..08a6730 100644
--- src/wp-admin/includes/class-wp-posts-list-table.php
+++ src/wp-admin/includes/class-wp-posts-list-table.php
@@ -1523,8 +1523,6 @@ class WP_Posts_List_Table extends WP_List_Table {
 			</label>
 
 	<?php	endif; // !$bulk
-
-			if ( 'page' === $screen->post_type ) :
 	?>
 
 			<label>
@@ -1538,12 +1536,11 @@ class WP_Posts_List_Table extends WP_List_Table {
 					$default_title = apply_filters( 'default_page_template_title',  __( 'Default Template' ), 'quick-edit' );
     				?>
 					<option value="default"><?php echo esc_html( $default_title ); ?></option>
-					<?php page_template_dropdown() ?>
+					<?php page_template_dropdown( $post->page_template, $screen->post_type ) ?>
 				</select>
 			</label>
 
 	<?php
-			endif; // page post_type
 		endif; // page-attributes
 	?>
 
diff --git src/wp-admin/includes/meta-boxes.php src/wp-admin/includes/meta-boxes.php
index 2d12faf..5915777 100644
--- src/wp-admin/includes/meta-boxes.php
+++ src/wp-admin/includes/meta-boxes.php
@@ -785,8 +785,7 @@ function post_revisions_meta_box( $post ) {
  * @param object $post
  */
 function page_attributes_meta_box($post) {
-	$post_type_object = get_post_type_object($post->post_type);
-	if ( $post_type_object->hierarchical ) {
+	if ( is_post_type_hierarchical( $post->post_type ) ) {
 		$dropdown_args = array(
 			'post_type'        => $post->post_type,
 			'exclude_tree'     => $post->ID,
@@ -817,8 +816,9 @@ function page_attributes_meta_box($post) {
 <?php
 		} // end empty pages check
 	} // end hierarchical check.
-	if ( 'page' == $post->post_type && 0 != count( get_page_templates( $post ) ) && get_option( 'page_for_posts' ) != $post->ID ) {
-		$template = !empty($post->page_template) ? $post->page_template : false;
+
+	if ( 0 < count( get_page_templates( $post ) ) && get_option( 'page_for_posts' ) != $post->ID ) {
+		$template = ! empty( $post->page_template ) ? $post->page_template : false;
 		?>
 <p><strong><?php _e('Template') ?></strong><?php
 	/**
@@ -832,7 +832,7 @@ function page_attributes_meta_box($post) {
 	 */
 	do_action( 'page_attributes_meta_box_template', $template, $post );
 ?></p>
-<label class="screen-reader-text" for="page_template"><?php _e('Page Template') ?></label><select name="page_template" id="page_template">
+<label class="screen-reader-text" for="page_template"><?php _e('Template') ?></label><select name="page_template" id="page_template">
 <?php
 /**
  * Filters the title of the default page template displayed in the drop-down.
@@ -846,7 +846,7 @@ function page_attributes_meta_box($post) {
 $default_title = apply_filters( 'default_page_template_title',  __( 'Default Template' ), 'meta-box' );
 ?>
 <option value="default"><?php echo esc_html( $default_title ); ?></option>
-<?php page_template_dropdown($template); ?>
+<?php page_template_dropdown( $template, $post->post_type ); ?>
 </select>
 <?php
 	} ?>
diff --git src/wp-admin/includes/template.php src/wp-admin/includes/template.php
index 4eac951..2a75523 100644
--- src/wp-admin/includes/template.php
+++ src/wp-admin/includes/template.php
@@ -293,14 +293,15 @@ function get_inline_data($post) {
 	<div class="ss">' . mysql2date( 's', $post->post_date, false ) . '</div>
 	<div class="post_password">' . esc_html( $post->post_password ) . '</div>';
 
-	if ( $post_type_object->hierarchical )
+	if ( $post_type_object->hierarchical ) {
 		echo '<div class="post_parent">' . $post->post_parent . '</div>';
+	}
 
-	if ( $post->post_type == 'page' )
-		echo '<div class="page_template">' . esc_html( get_post_meta( $post->ID, '_wp_page_template', true ) ) . '</div>';
+	echo '<div class="page_template">' . esc_html( $post->page_template ) . '</div>';
 
-	if ( post_type_supports( $post->post_type, 'page-attributes' ) )
+	if ( post_type_supports( $post->post_type, 'page-attributes' ) ) {
 		echo '<div class="menu_order">' . $post->menu_order . '</div>';
+	}
 
 	$taxonomy_names = get_object_taxonomies( $post->post_type );
 	foreach ( $taxonomy_names as $taxonomy_name) {
@@ -761,11 +762,13 @@ function touch_time( $edit = 1, $for_post = 1, $tab_index = 0, $multi = 0 ) {
  * Print out option HTML elements for the page templates drop-down.
  *
  * @since 1.5.0
+ * @since 4.7.0 Added the `$post_type` parameter.
  *
- * @param string $default Optional. The template file name. Default empty.
+ * @param string $default   Optional. The template file name. Default empty.
+ * @param string $post_type Optional. Post type to get templates for. Default 'post'.
  */
-function page_template_dropdown( $default = '' ) {
-	$templates = get_page_templates( get_post() );
+function page_template_dropdown( $default = '', $post_type = 'page' ) {
+	$templates = get_page_templates( null, $post_type );
 	ksort( $templates );
 	foreach ( array_keys( $templates ) as $template ) {
 		$selected = selected( $default, $templates[ $template ], false );
diff --git src/wp-admin/includes/theme.php src/wp-admin/includes/theme.php
index 95aaec1..905e1be 100644
--- src/wp-admin/includes/theme.php
+++ src/wp-admin/includes/theme.php
@@ -102,12 +102,14 @@ function delete_theme($stylesheet, $redirect = '') {
  * Get the Page Templates available in this theme
  *
  * @since 1.5.0
+ * @since 4.7.0 Added the `$post_type` parameter.
  *
- * @param WP_Post|null $post Optional. The post being edited, provided for context.
+ * @param WP_Post|null $post      Optional. The post being edited, provided for context.
+ * @param string       $post_type Optional. Post type to get the templates for. Default 'page'.
  * @return array Key is the template name, value is the filename of the template
  */
-function get_page_templates( $post = null ) {
-	return array_flip( wp_get_theme()->get_page_templates( $post ) );
+function get_page_templates( $post = null, $post_type = 'page' ) {
+	return array_flip( wp_get_theme()->get_page_templates( $post, $post_type ) );
 }
 
 /**
diff --git src/wp-includes/class-wp-post.php src/wp-includes/class-wp-post.php
index a21776f..c966934 100644
--- src/wp-includes/class-wp-post.php
+++ src/wp-includes/class-wp-post.php
@@ -254,7 +254,7 @@ final class WP_Post {
 			return true;
 
 		if ( 'page_template' == $key )
-			return ( 'page' == $this->post_type );
+			return true;
 
 		if ( 'post_category' == $key )
 		   return true;
diff --git src/wp-includes/class-wp-theme.php src/wp-includes/class-wp-theme.php
index 40af39d..80f8362 100644
--- src/wp-includes/class-wp-theme.php
+++ src/wp-includes/class-wp-theme.php
@@ -1005,56 +1005,99 @@ final class WP_Theme implements ArrayAccess {
 	}
 
 	/**
-	 * Returns the theme's page templates.
+	 * Returns the theme's post templates.
 	 *
-	 * @since 3.4.0
+	 * @since 4.7.0
 	 * @access public
 	 *
-	 * @param WP_Post|null $post Optional. The post being edited, provided for context.
-	 * @return array Array of page templates, keyed by filename, with the value of the translated header name.
+	 * @return array Array of page templates, keyed by filename and post type,
+	 *               with the value of the translated header name.
 	 */
-	public function get_page_templates( $post = null ) {
+	public function get_post_templates() {
 		// If you screw up your current theme and we invalidate your parent, most things still work. Let it slide.
-		if ( $this->errors() && $this->errors()->get_error_codes() !== array( 'theme_parent_invalid' ) )
+		if ( $this->errors() && $this->errors()->get_error_codes() !== array( 'theme_parent_invalid' ) ) {
 			return array();
+		}
 
-		$page_templates = $this->cache_get( 'page_templates' );
+		$post_templates = $this->cache_get( 'post_templates' );
 
-		if ( ! is_array( $page_templates ) ) {
-			$page_templates = array();
+		if ( ! is_array( $post_templates ) ) {
+			$post_templates = array();
 
 			$files = (array) $this->get_files( 'php', 1 );
 
 			foreach ( $files as $file => $full_path ) {
-				if ( ! preg_match( '|Template Name:(.*)$|mi', file_get_contents( $full_path ), $header ) )
+				if ( ! preg_match( '|Template Name:(.*)$|mi', file_get_contents( $full_path ), $header ) ) {
 					continue;
-				$page_templates[ $file ] = _cleanup_header_comment( $header[1] );
+				}
+
+				$types = array( 'page' );
+				if ( preg_match( '|Template Type:(.*)$|mi', file_get_contents( $full_path ), $type ) ) {
+					$types = explode( ',', _cleanup_header_comment( $type[1] ) );
+				}
+
+				foreach ( $types as $type ) {
+					$type = trim( $type );
+					if ( ! isset( $post_templates[ $type ] ) ) {
+						$post_templates[ $type ] = array();
+					}
+
+					$post_templates[ $type ][ $file ] = _cleanup_header_comment( $header[1] );
+				}
 			}
 
-			$this->cache_add( 'page_templates', $page_templates );
+			$this->cache_add( 'page_templates', $post_templates );
 		}
 
 		if ( $this->load_textdomain() ) {
-			foreach ( $page_templates as &$page_template ) {
-				$page_template = $this->translate_header( 'Template Name', $page_template );
+			foreach ( $post_templates as &$post_type ) {
+				foreach ( $post_type as &$post_template ) {
+					$post_template = $this->translate_header( 'Template Name', $post_template );
+				}
 			}
 		}
 
-		if ( $this->parent() )
-			$page_templates += $this->parent()->get_page_templates( $post );
+		return $post_templates;
+	}
+
+	/**
+	 * Returns the theme's post templates for a given post type.
+	 *
+	 * @since 3.4.0
+	 * @since 4.7.0 Added the `$post_type` parameter.
+	 * @access public
+	 *
+	 * @param WP_Post|null $post      Optional. The post being edited, provided for context.
+	 * @param string       $post_type Optional. Post type to get the templates for. Default 'page'.
+	 *                                If a post is provided, its post type is used.
+	 * @return array Array of page templates, keyed by filename, with the value of the translated header name.
+	 */
+	public function get_page_templates( $post = null, $post_type = 'page' ) {
+		if ( $post ) {
+			$post_type = get_post_type( $post );
+		}
+
+		$post_templates = $this->get_post_templates();
+		$post_templates = isset( $post_templates[ $post_type ] ) ? $post_templates[ $post_type ] : array();
+
+		if ( $this->parent() ) {
+			$post_templates += $this->parent()->get_page_templates( $post );
+		}
 
 		/**
 		 * Filters list of page templates for a theme.
 		 *
 		 * @since 3.9.0
 		 * @since 4.4.0 Converted to allow complete control over the `$page_templates` array.
+		 * @since 4.7.0 Added the `$post_type` parameter.
 		 *
-		 * @param array        $page_templates Array of page templates. Keys are filenames,
+		 * @param array        $post_templates Array of page templates. Keys are filenames,
 		 *                                     values are translated names.
 		 * @param WP_Theme     $this           The theme object.
 		 * @param WP_Post|null $post           The post being edited, provided for context, or null.
+		 * @param string       $post_type      Post type to get the templates for.
 		 */
-		return (array) apply_filters( 'theme_page_templates', $page_templates, $this, $post );
+		return (array) apply_filters( 'theme_page_templates', $post_templates, $this, $post, $post_type );
 	}
 
 	/**
diff --git src/wp-includes/post-template.php src/wp-includes/post-template.php
index 0c1d1e4..94f6e5d 100644
--- src/wp-includes/post-template.php
+++ src/wp-includes/post-template.php
@@ -1613,14 +1613,12 @@ function get_the_password_form( $post = 0 ) {
  *
  * @since 2.5.0
  * @since 4.2.0 The `$template` parameter was changed to also accept an array of page templates.
+ * @since 4.7.0 Now supports any post type, not just pages.
  *
  * @param string|array $template The specific template name or array of templates to match.
  * @return bool True on success, false on failure.
  */
 function is_page_template( $template = '' ) {
-	if ( ! is_page() )
-		return false;
-
 	$page_template = get_page_template_slug( get_queried_object_id() );
 
 	if ( empty( $template ) )
@@ -1641,21 +1639,28 @@ function is_page_template( $template = '' ) {
 }
 
 /**
- * Get the specific template name for a page.
+ * Get the specific template name for a given post.
  *
  * @since 3.4.0
+ * @since 4.7.0 Now supports all post types.
  *
- * @param int $post_id Optional. The page ID to check. Defaults to the current post, when used in the loop.
+ * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
  * @return string|false Page template filename. Returns an empty string when the default page template
- * 	is in use. Returns false if the post is not a page.
+ * 	is in use. Returns false if the post does not exist.
  */
-function get_page_template_slug( $post_id = null ) {
-	$post = get_post( $post_id );
-	if ( ! $post || 'page' != $post->post_type )
+function get_page_template_slug( $post = null ) {
+	$post = get_post( $post );
+
+	if ( ! $post ) {
 		return false;
+	}
+
 	$template = get_post_meta( $post->ID, '_wp_page_template', true );
-	if ( ! $template || 'default' == $template )
+
+	if ( ! $template || 'default' == $template ) {
 		return '';
+	}
+
 	return $template;
 }
 
diff --git src/wp-includes/post.php src/wp-includes/post.php
index ced823c..f581017 100644
--- src/wp-includes/post.php
+++ src/wp-includes/post.php
@@ -1242,6 +1242,7 @@ function _post_type_meta_capabilities( $capabilities = null ) {
  *                       post types. Default is 'Parent Page:'.
  * - `all_items` - Label to signify all items in a submenu link. Default is 'All Posts' / 'All Pages'.
  * - `archives` - Label for archives in nav menus. Default is 'Post Archives' / 'Page Archives'.
+ * - `attributes` - Label for the attributes meta box. Default is 'Post Attributes' / 'Page Attributes'.
  * - `insert_into_item` - Label for the media frame button. Default is 'Insert into post' / 'Insert into page'.
  * - `uploaded_to_this_item` - Label for the media frame filter. Default is 'Uploaded to this post' /
  *                           'Uploaded to this page'.
@@ -1267,6 +1268,7 @@ function _post_type_meta_capabilities( $capabilities = null ) {
  * @since 4.4.0 Added the `insert_into_item`, `uploaded_to_this_item`, `filter_items_list`,
  *              `items_list_navigation`, and `items_list` labels.
  * @since 4.6.0 Converted the `$post_type` parameter to accept a WP_Post_Type object.
+ * @since 4.7.0 Added the `attributes` label.
  *
  * @access private
  *
@@ -1288,6 +1290,7 @@ function get_post_type_labels( $post_type_object ) {
 		'parent_item_colon' => array( null, __('Parent Page:') ),
 		'all_items' => array( __( 'All Posts' ), __( 'All Pages' ) ),
 		'archives' => array( __( 'Post Archives' ), __( 'Page Archives' ) ),
+		'attributes' => array( __( 'Post Attributes' ), __( 'Page Attributes' ) ),
 		'insert_into_item' => array( __( 'Insert into post' ), __( 'Insert into page' ) ),
 		'uploaded_to_this_item' => array( __( 'Uploaded to this post' ), __( 'Uploaded to this page' ) ),
 		'featured_image' => array( __( 'Featured Image' ), __( 'Featured Image' ) ),
@@ -3307,7 +3310,7 @@ function wp_insert_post( $postarr, $wp_error = false ) {
 
 	$post = get_post( $post_ID );
 
-	if ( ! empty( $postarr['page_template'] ) && 'page' == $data['post_type'] ) {
+	if ( ! empty( $postarr['page_template'] ) ) {
 		$post->page_template = $postarr['page_template'];
 		$page_templates = wp_get_theme()->get_page_templates( $post );
 		if ( 'default' != $postarr['page_template'] && ! isset( $page_templates[ $postarr['page_template'] ] ) ) {
diff --git src/wp-includes/template.php src/wp-includes/template.php
index 946732f..120e698 100644
--- src/wp-includes/template.php
+++ src/wp-includes/template.php
@@ -432,6 +432,10 @@ function get_single_template() {
 	$templates = array();
 
 	if ( ! empty( $object->post_type ) ) {
+		$template = get_page_template_slug( $object );
+		if ( $template && 0 === validate_file( $template ) ) {
+			$templates[] = $template;
+		}
 
 		$name_decoded = urldecode( $object->post_name );
 		if ( $name_decoded !== $object->post_name ) {
diff --git tests/phpunit/data/themedir1/page-templates/subdir/template-sub-dir-post-types.php tests/phpunit/data/themedir1/page-templates/subdir/template-sub-dir-post-types.php
new file mode 100644
index 0000000..7f96d18
--- /dev/null
+++ tests/phpunit/data/themedir1/page-templates/subdir/template-sub-dir-post-types.php
@@ -0,0 +1,5 @@
+<?php
+/*
+    Template Name: Sub Dir
+    Template Type: post, foo
+ */
diff --git tests/phpunit/data/themedir1/page-templates/template-top-level-post-types.php tests/phpunit/data/themedir1/page-templates/template-top-level-post-types.php
new file mode 100644
index 0000000..19ece9e
--- /dev/null
+++ tests/phpunit/data/themedir1/page-templates/template-top-level-post-types.php
@@ -0,0 +1,5 @@
+<?php
+/*
+    Template Name: Top Level
+    Template Type: post, foo
+ */
diff --git tests/phpunit/tests/admin/includesTheme.php tests/phpunit/tests/admin/includesTheme.php
index 382c6bb..ba76bf1 100644
--- tests/phpunit/tests/admin/includesTheme.php
+++ tests/phpunit/tests/admin/includesTheme.php
@@ -48,21 +48,41 @@ class Tests_Admin_includesTheme extends WP_UnitTestCase {
 
 		switch_theme( $theme['Template'], $theme['Stylesheet'] );
 
-		$templates = get_page_templates();
-		$this->assertCount( 3, $templates );
-		$this->assertEquals( "template-top-level.php", $templates['Top Level'] );
-		$this->assertEquals( "subdir/template-sub-dir.php", $templates['Sub Dir'] );
-		$this->assertEquals( "template-header.php", $templates['This Template Header Is On One Line'] );
+		$this->assertEqualSetsWithIndex( array(
+			'Top Level'                           => 'template-top-level.php',
+			'Sub Dir'                             => 'subdir/template-sub-dir.php',
+			'This Template Header Is On One Line' => 'template-header.php',
+		), get_page_templates() );
 
 		$theme = wp_get_theme( 'page-templates' );
 		$this->assertNotEmpty( $theme );
 
 		switch_theme( $theme['Template'], $theme['Stylesheet'] );
 
-		$templates = get_page_templates();
-		$this->assertCount( 3, $templates );
-		$this->assertEquals( "template-top-level.php", $templates['Top Level'] );
-		$this->assertEquals( "subdir/template-sub-dir.php", $templates['Sub Dir'] );
-		$this->assertEquals( "template-header.php", $templates['This Template Header Is On One Line'] );
+		$this->assertEqualSetsWithIndex( array(
+			'Top Level'                           => 'template-top-level.php',
+			'Sub Dir'                             => 'subdir/template-sub-dir.php',
+			'This Template Header Is On One Line' => 'template-header.php',
+		), get_page_templates() );
+	}
+
+	/**
+	 * @ticket 18375
+	 */
+	function test_page_templates_different_post_types() {
+		$theme = wp_get_theme( 'page-templates' );
+		$this->assertNotEmpty( $theme );
+
+		switch_theme( $theme['Template'], $theme['Stylesheet'] );
+
+		$this->assertEqualSetsWithIndex( array(
+			'Top Level' => 'template-top-level-post-types.php',
+			'Sub Dir'   => 'subdir/template-sub-dir-post-types.php',
+		), get_page_templates( null, 'foo' ) );
+		$this->assertEqualSetsWithIndex( array(
+			'Top Level' => 'template-top-level-post-types.php',
+			'Sub Dir'   => 'subdir/template-sub-dir-post-types.php',
+		), get_page_templates( null, 'post' ) );
+		$this->assertEquals( array(), get_page_templates( null, 'bar' ) );
 	}
 }
diff --git tests/phpunit/tests/post/objects.php tests/phpunit/tests/post/objects.php
index 5ad92c6..fb376a2 100644
--- tests/phpunit/tests/post/objects.php
+++ tests/phpunit/tests/post/objects.php
@@ -134,6 +134,9 @@ class Tests_Post_Objects extends WP_UnitTestCase {
 		$this->assertEquals( array( 'Bar', 'Baz', 'Foo' ), $post['tags_input'] );
 	}
 
+	/**
+	 * @ticket 18375
+	 */
 	function test_get_page_template_property() {
 		$post_id = self::factory()->post->create();
 		$post = get_post( $post_id );
@@ -145,12 +148,6 @@ class Tests_Post_Objects extends WP_UnitTestCase {
 		update_post_meta( $post_id, '_wp_page_template', 'foo.php' );
 		$template = get_post_meta( $post->ID, '_wp_page_template', true );
 		$this->assertEquals( 'foo.php', $template );
-		// The post is not a page so the template is still empty
-		$this->assertEquals( '', $post->page_template );
-
-		// Now the post is a page and should retrieve the template
-		wp_update_post( array( 'ID' => $post->ID, 'post_type' => 'page' ) );
-		$post = get_post( $post_id );
 		$this->assertEquals( $template, $post->page_template );
 	}
 
diff --git tests/phpunit/tests/post/template.php tests/phpunit/tests/post/template.php
index ac5958d..062b04a 100644
--- tests/phpunit/tests/post/template.php
+++ tests/phpunit/tests/post/template.php
@@ -271,16 +271,32 @@ NO;
 
 	/**
 	 * @ticket 31389
+	 * @ticket 18375
 	 */
 	public function test_get_page_template_slug_non_page() {
-		$post_id = self::factory()->post->create( array(
-			'post_type' => 'post',
-		) );
+		$post_id = self::factory()->post->create();
+
+		$this->assertEquals( '', get_page_template_slug( $post_id ) );
+
+		update_post_meta( $post_id, '_wp_page_template', 'default' );
 
-		$this->assertFalse( get_page_template_slug( $post_id ) );
+		$this->assertEquals( '', get_page_template_slug( $post_id ) );
+
+		update_post_meta( $post_id, '_wp_page_template', 'example.php' );
+		$this->assertEquals( 'example.php', get_page_template_slug( $post_id ) );
+	}
+
+	/**
+	 * @ticket 18375
+	 */
+	public function test_get_page_template_slug_non_page_from_loop() {
+		$post_id = self::factory()->post->create();
+
+		update_post_meta( $post_id, '_wp_page_template', 'example.php' );
 
 		$this->go_to( get_permalink( $post_id ) );
-		$this->assertFalse( get_page_template_slug() );
+
+		$this->assertEquals( 'example.php', get_page_template_slug() );
 	}
 
 	/**
diff --git tests/phpunit/tests/query/conditionals.php tests/phpunit/tests/query/conditionals.php
index 21963c7..debd18d 100644
--- tests/phpunit/tests/query/conditionals.php
+++ tests/phpunit/tests/query/conditionals.php
@@ -1044,6 +1044,17 @@ class Tests_Query_Conditionals extends WP_UnitTestCase {
 	}
 
 	/**
+	 * @ticket 18375
+	 */
+	function test_is_page_template_other_post_type() {
+		$post_id = self::factory()->post->create( array( 'post_type' => 'post' ) );
+		update_post_meta( $post_id, '_wp_page_template', 'example.php' );
+		$this->go_to( get_post_permalink( $post_id ) );
+		$this->assertFalse( is_page_template( array( 'test.php' ) ) );
+		$this->assertTrue( is_page_template( array( 'test.php', 'example.php' ) ) );
+	}
+
+	/**
 	 * @ticket 35902
 	 */
 	public function test_is_attachment_should_not_match_numeric_id_to_post_title_beginning_with_id() {
diff --git tests/phpunit/tests/template.php tests/phpunit/tests/template.php
index 00030f2..d303c57 100644
--- tests/phpunit/tests/template.php
+++ tests/phpunit/tests/template.php
@@ -36,6 +36,7 @@ class Tests_Template extends WP_UnitTestCase {
 			'post_date' => '1984-02-25 12:34:56',
 		) );
 		set_post_format( self::$post, 'quote' );
+		add_post_meta( self::$post->ID, '_wp_page_template', 'templates/post.php' );
 	}
 
 	public function setUp() {
@@ -203,8 +204,12 @@ class Tests_Template extends WP_UnitTestCase {
 		) );
 	}
 
+	/**
+	 * @ticket 18375
+	 */
 	public function test_single_template_hierarchy_for_post() {
 		$this->assertTemplateHierarchy( get_permalink( self::$post ), array(
+			'templates/post.php',
 			'single-post-post-name-😀.php',
 			'single-post-post-name-%f0%9f%98%80.php',
 			'single-post.php',
@@ -228,6 +233,26 @@ class Tests_Template extends WP_UnitTestCase {
 		) );
 	}
 
+	/**
+	 * @ticket 18375
+	 */
+	public function test_single_template_hierarchy_for_custom_post_type_with_page_template() {
+		$cpt = self::factory()->post->create_and_get( array(
+			'post_type' => 'cpt',
+			'post_name' => 'cpt-name-😀',
+		) );
+		add_post_meta( $cpt->ID, '_wp_page_template', 'templates/cpt.php' );
+
+		$this->assertTemplateHierarchy( get_permalink( $cpt ), array(
+			'templates/cpt.php',
+			'single-cpt-cpt-name-😀.php',
+			'single-cpt-cpt-name-%f0%9f%98%80.php',
+			'single-cpt.php',
+			'single.php',
+			'singular.php',
+		) );
+	}
+
 	public function test_attachment_template_hierarchy() {
 		$attachment = self::factory()->attachment->create_and_get( array(
 			'post_name'      => 'attachment-name-😀',
