Repository: not-an-aardvark/eslint-plugin-eslint-plugin (js)

Issue:
Rule: prefer `output: null` to assert that a test case is not autofixed
Disallows invalid `RuleTester` test cases with the output the same as the code.

Invalid:

```js
/* eslint eslint-plugin/prefer-output-null: error */

new RuleTester().run('foo', rule, {
  valid: [],
  invalid: [
    {
      code: 'foo',
      output: 'foo',
      errors: 1
    }
  ]
});
```

Valid:

```js
/* eslint eslint-plugin/prefer-output-null: error */

new RuleTester().run('foo', rule, {
  valid: [],
  invalid: [
    {
      code: 'foo',
      output: null,
      errors: 1
    }
  ]
});
```

```js
/* eslint eslint-plugin/prefer-output-null: error */

new RuleTester().run('foo', rule, {
  valid: [],
  invalid: [
    {
      code: 'foo',
      output: 'bar',
      errors: 1
    }
  ]
});
```

Pull request:
New: rule prefer-output-null
fixes #19 

Patch:
diff --git a/README.md b/README.md
index 424d486..80da497 100644
--- a/README.md
+++ b/README.md
@@ -53,6 +53,7 @@ Name | ✔️ | 🛠 | Description
 [no-identical-tests](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/no-identical-tests.md) | | 🛠 | Disallows identical tests
 [no-missing-placeholders](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/no-missing-placeholders.md) | ✔️ | | Disallows missing placeholders in rule report messages
 [no-useless-token-range](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/no-useless-token-range.md) | ✔️ | 🛠 | Disallows unnecessary calls to sourceCode.getFirstToken and sourceCode.getLastToken
+[prefer-output-null](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/prefer-output-null.md) | | | Disallows invalid RuleTester test cases with the output the same as the code.
 [prefer-placeholders](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/prefer-placeholders.md) | | | Disallows template literals as report messages
 [report-message-format](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/report-message-format.md) | | | Enforces a consistent format for report messages
 [require-meta-fixable](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/require-meta-fixable.md) | ✔️ | | Requires a `meta.fixable` property for fixable rules
diff --git a/docs/rules/prefer-output-null.md b/docs/rules/prefer-output-null.md
new file mode 100644
index 0000000..3a95b52
--- /dev/null
+++ b/docs/rules/prefer-output-null.md
@@ -0,0 +1,31 @@
+# Disallows invalid RuleTester test cases with the output the same as the code. (prefer-output-null)
+
+## Rule Details
+
+The rule reports an error if it encounters a test case where the output is the same as the code.
+
+Examples of **incorrect** code for this rule:
+
+```js
+/* eslint eslint-plugin/prefer-output-null: error */
+
+new RuleTester().run('foo', bar, {
+    valid: [],
+    invalid: [
+      { code: 'foo', output: 'foo', errors: [{ message: 'bar' }] },
+    ]
+});
+```
+
+Examples of **correct** code for this rule:
+
+```js
+/* eslint eslint-plugin/prefer-output-null: error */
+
+new RuleTester().run('foo', bar, {
+    valid: [],
+    invalid: [
+      { code: 'foo', output: null, errors: [{ message: 'bar' }] },
+    ]
+});
+```
diff --git a/lib/rules/prefer-output-null.js b/lib/rules/prefer-output-null.js
new file mode 100644
index 0000000..9f31645
--- /dev/null
+++ b/lib/rules/prefer-output-null.js
@@ -0,0 +1,61 @@
+/**
+ * @fileoverview disallows invalid RuleTester test cases with the output the same as the code.
+ * @author 薛定谔的猫<hh_2013@foxmail.com>
+ */
+
+'use strict';
+
+const utils = require('../utils');
+
+// ------------------------------------------------------------------------------
+// Rule Definition
+// ------------------------------------------------------------------------------
+
+module.exports = {
+  meta: {
+    docs: {
+      description: 'disallows invalid RuleTester test cases with the output the same as the code.',
+      category: 'Tests',
+      recommended: false,
+    },
+    fixable: null,
+    schema: [],
+  },
+
+  create (context) {
+    // ----------------------------------------------------------------------
+    // Public
+    // ----------------------------------------------------------------------
+
+    const message = 'Use `output: null` to assert that a test case is not autofixed.';
+    const sourceCode = context.getSourceCode();
+
+    return {
+      Program (ast) {
+        utils.getTestInfo(context, ast).forEach(testRun => {
+          (testRun.invalid || []).forEach(test => {
+            /**
+            * Get a test case's giving keyname node.
+            * @param {string} the keyname to find.
+            * @returns {Node} found node; if not found, return null;
+            */
+            function getTestInfo (key) {
+              const res = test.properties.filter(item => item.key.name === key);
+              return res.length ? res[res.length - 1] : null;
+            }
+
+            const code = getTestInfo('code');
+            const output = getTestInfo('output');
+
+            if (output && sourceCode.getText(output.value) === sourceCode.getText(code.value)) {
+              context.report({
+                node: test,
+                message,
+              });
+            }
+          });
+        });
+      },
+    };
+  },
+};


Test patch:
diff --git a/tests/lib/rules/no-deprecated-report-api.js b/tests/lib/rules/no-deprecated-report-api.js
index f0eeafe..e5e3559 100644
--- a/tests/lib/rules/no-deprecated-report-api.js
+++ b/tests/lib/rules/no-deprecated-report-api.js
@@ -124,13 +124,7 @@ ruleTester.run('no-deprecated-report-api', rule, {
           }
         };
       `,
-      output: `
-        module.exports = {
-          create(context) {
-            context.report(theNode, theMessage, theData, theFix);
-          }
-        };
-      `,
+      output: null,
       errors: [ERROR],
     },
     {
@@ -175,13 +169,7 @@ ruleTester.run('no-deprecated-report-api', rule, {
           }
         };
       `,
-      output: `
-        module.exports = {
-          create(notContext) {
-            notContext.report(theNode, theMessage, theData, theFix);
-          }
-        };
-      `,
+      output: null,
       errors: [ERROR],
     },
     {
@@ -218,13 +206,7 @@ ruleTester.run('no-deprecated-report-api', rule, {
           }
         };
       `,
-      output: `
-        module.exports = {
-          create(context) {
-            context.report(theNode, theLocation, theMessage, theData, theFix, somethingElse, somethingElse, somethingElse);
-          }
-        };
-      `,
+      output: null,
       errors: [ERROR],
     },
   ],
diff --git a/tests/lib/rules/prefer-output-null.js b/tests/lib/rules/prefer-output-null.js
new file mode 100644
index 0000000..24ee3ea
--- /dev/null
+++ b/tests/lib/rules/prefer-output-null.js
@@ -0,0 +1,55 @@
+/**
+ * @fileoverview disallows invalid RuleTester test cases with the output the same as the code.
+ * @author 薛定谔的猫<hh_2013@foxmail.com>
+ */
+
+'use strict';
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+const rule = require('../../../lib/rules/prefer-output-null');
+const RuleTester = require('eslint').RuleTester;
+
+const ERROR = { message: 'Use `output: null` to assert that a test case is not autofixed.' };
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+const ruleTester = new RuleTester();
+ruleTester.run('prefer-output-null', rule, {
+  valid: [
+    `
+      new RuleTester().run('foo', bar, {
+        valid: [],
+        invalid: [
+          {code: 'foo', output: 'bar', errors: ['bar']},
+        ]
+      });
+    `,
+    `
+      new RuleTester().run('foo', bar, {
+        valid: [],
+        invalid: [
+          {code: 'foo', output: null, errors: ['bar']},
+        ]
+      });
+    `,
+  ],
+
+  invalid: [
+    {
+      code: `
+        new RuleTester().run('foo', bar, {
+          valid: [],
+          invalid: [
+            {code: 'foo', output: 'foo', errors: ['bar']},
+          ]
+        });
+      `,
+      errors: [ERROR],
+    },
+  ],
+});