Repository: ember-cli/eslint-plugin-ember (js)

Issue:
New Rule: `no-replace-test-comments`
### What
- disallow 'Replace this with your real tests' comments

### Why
- we should encourage folks to use ember-cli + generators
- for those in a rush / without strong reviews, you end up with plenty of checked in test files that only have canary tests:
```javascript
  // Replace this with your real tests.
  test('it exists', function (assert) {
    let service = this.owner.lookup('service:company');
    assert.ok(service);
  });
```
- this rule will nudge developers to start writing a meaningful test earlier in the process

Pull request description:
Add new rule `no-replace-test-comments`
### What
- disallow 'Replace this with your real tests' comments

### Why
- we should encourage folks to use ember-cli + generators
- for those in a rush / without strong reviews, you end up with plenty of checked in test files that only have canary tests:
```javascript
  // Replace this with your real tests.
  test('it exists', function (assert) {
    let service = this.owner.lookup('service:company');
    assert.ok(service);
  });
```
- this rule will nudge developers to start writing a meaningful test earlier in the process

Fixes #717 

Patch:
diff --git a/README.md b/README.md
index de1e4613..f5a4a5a5 100644
--- a/README.md
+++ b/README.md
@@ -144,6 +144,7 @@ Rules are grouped by category to help you understand their purpose. Each rule ha
 |:---|:--------|:------------|
 |  | [no-legacy-test-waiters](./docs/rules/no-legacy-test-waiters.md) | disallow the use of the legacy test waiter APIs. |
 |  | [no-pause-test](./docs/rules/no-pause-test.md) | disallow usage of the `pauseTest` helper in tests |
+|  | [no-replace-test-comments](./docs/rules/no-replace-test-comments.md) | disallow 'Replace this with your real tests' comments in test files |
 |  | [no-test-and-then](./docs/rules/no-test-and-then.md) | disallow usage of the `andThen` test wait helper |
 |  | [no-test-import-export](./docs/rules/no-test-import-export.md) | disallow importing of "-test.js" in a test file and exporting from a test file |
 |  | [no-test-module-for](./docs/rules/no-test-module-for.md) | disallow usage of `moduleFor`, `moduleForComponent`, etc |
diff --git a/lib/index.js b/lib/index.js
index 65c054c2..909b3d5e 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -43,6 +43,7 @@ module.exports = {
     'no-pause-test': require('./rules/no-pause-test'),
     'no-private-routing-service': require('./rules/no-private-routing-service'),
     'no-proxies': require('./rules/no-proxies'),
+    'no-replace-test-comments': require('./rules/no-replace-test-comments'),
     'no-restricted-resolver-tests': require('./rules/no-restricted-resolver-tests'),
     'no-side-effects': require('./rules/no-side-effects'),
     'no-test-and-then': require('./rules/no-test-and-then'),
diff --git a/lib/recommended-rules.js b/lib/recommended-rules.js
index c90060e2..28fd48e3 100644
--- a/lib/recommended-rules.js
+++ b/lib/recommended-rules.js
@@ -46,6 +46,7 @@ module.exports = {
   "ember/no-pause-test": "off",
   "ember/no-private-routing-service": "off",
   "ember/no-proxies": "off",
+  "ember/no-replace-test-comments": "off",
   "ember/no-restricted-resolver-tests": "error",
   "ember/no-side-effects": "error",
   "ember/no-test-and-then": "off",


Test patch:
diff --git a/docs/rules/no-replace-test-comments.md b/docs/rules/no-replace-test-comments.md
new file mode 100644
index 00000000..6234275a
--- /dev/null
+++ b/docs/rules/no-replace-test-comments.md
@@ -0,0 +1,46 @@
+# no-replace-test-comments
+
+Ember developers using blueprints to generate classes should write real tests.
+
+Leaving the default test comment in place is a sign of a rushed class.
+
+## Rule Details
+
+This rule aims to nudge developers into writing more/better tests.
+
+It aims to do this by complaining at them early about a default test file.
+
+This rule only fires for test files (ending in '-test.js' or '-test.ts')
+
+This will especially push TDD (test-driven development) on repos with githooks that enforce lint early.
+
+## Examples
+
+Examples of **incorrect** code for this rule:
+
+```js
+// Replace this with your real tests.
+test('it exists', function(assert) {
+  const service = this.owner.lookup('service:company');
+  assert.ok(service);
+});
+```
+
+Examples of **correct** code for this rule:
+
+```js
+test('it has a purpose beyond mere existence', function(assert) {
+  const service = this.owner.lookup('service:company');
+  set(service, 'company', myCompanyMock);
+  assert.equal(service.isOnboardingComplete, true, 'the computed property works as expected');
+});
+```
+
+## Migration
+
+- The [testing guides](https://guides.emberjs.com/release/testing/testing-components/) shall be your guide
+- Consider a code coverage tool like [ember-cli-code-coverage](https://github.com/kategengler/ember-cli-code-coverage) as well
+
+## References
+
+- [Learn Test Driven Development in Ember](https://learntdd.in/ember/)
diff --git a/lib/rules/no-replace-test-comments.js b/lib/rules/no-replace-test-comments.js
new file mode 100644
index 00000000..a5397be3
--- /dev/null
+++ b/lib/rules/no-replace-test-comments.js
@@ -0,0 +1,56 @@
+'use strict';
+
+const emberUtils = require('../utils/ember');
+
+const ERROR_MESSAGE = "No 'Replace this with your real tests' comments. Add a substantive test.";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+  meta: {
+    type: 'suggestion',
+    docs: {
+      description: "disallow 'Replace this with your real tests' comments in test files",
+      category: 'Testing',
+      recommended: false,
+      url:
+        'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/no-replace-test-comments.md',
+    },
+    fixable: null,
+    schema: [],
+  },
+
+  ERROR_MESSAGE,
+
+  create(context) {
+    //----------------------------------------------------------------------
+    // Helpers
+    //----------------------------------------------------------------------
+
+    const checkForRealTestsComment = node => {
+      const { value = '' } = node || {};
+      const regex = /replace this with your real tests/i;
+      const message = ERROR_MESSAGE;
+      if (regex.test(value)) {
+        context.report({ node, message });
+      }
+    };
+
+    //----------------------------------------------------------------------
+    // Public
+    //----------------------------------------------------------------------
+
+    if (!emberUtils.isTestFile(context.getFilename())) {
+      return {};
+    }
+    return {
+      Program(/* node */) {
+        const sourceCode = context.getSourceCode() || {};
+        const comments = sourceCode.getAllComments() || [];
+        comments.forEach(checkForRealTestsComment);
+      },
+    };
+  },
+};
diff --git a/tests/lib/rules/no-replace-test-comments.js b/tests/lib/rules/no-replace-test-comments.js
new file mode 100644
index 00000000..60f53562
--- /dev/null
+++ b/tests/lib/rules/no-replace-test-comments.js
@@ -0,0 +1,40 @@
+'use strict';
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const RuleTester = require('eslint').RuleTester;
+const rule = require('../../../lib/rules/no-replace-test-comments');
+
+const { ERROR_MESSAGE } = rule;
+
+//------------------------------------------------------------------------------
+// Tests
+//------------------------------------------------------------------------------
+
+const ruleTester = new RuleTester();
+ruleTester.run('no-replace-test-comments', rule, {
+  valid: [
+    '// some harmless comment',
+    'myCodeWithoutAComment = "fooBar"',
+    {
+      filename: 'app/some-app-file.js',
+      code: '// Replace this with your real tests',
+    },
+  ],
+
+  invalid: [
+    {
+      filename: 'test/some-app-file-test.js',
+      code: '// Replace this with your real tests',
+      output: null,
+      errors: [
+        {
+          message: ERROR_MESSAGE,
+          type: 'Line',
+        },
+      ],
+    },
+  ],
+});