Repository: dbt-labs/dbt-core

Issue:
Make default test-paths and analysis-paths configs consistent
### Describe the bug
Currently, the default values for various `<resource>-paths` are:
```
source-paths: ['models']
macro-paths:['macros']
data-paths: ['data']
test-paths: ['test']
analysis-paths:  []
```
([source](https://github.com/fishtown-analytics/dbt/blob/dev/marian-anderson/core/dbt/config/project.py#L406-L407))

The defaults for `test-paths` and `analysis-paths`:
- Are not consistent with the other defaults (i.e. `['test']` instead of `['tests']`, and `[]` instead of `['analyses']`)
- Differ from the values set by `dbt init` which are `['tests']` and `['analysis']` respectively ([source](https://github.com/fishtown-analytics/dbt-starter-project/blob/master/dbt_project.yml#L16-L19)), 


| Config         | What I expect the default to be | The actual default | The value set by `dbt init` | 
|----------------|---------------------------------|--------------------|---------------------------| 
| `test-paths`     | `['tests']`                       | `['test']`           | `['tests']`                | 
| `analysis-paths` | `['analyses']`                    | `[]`                 | `['analysis']` (singular)              | 

We should:
- Update the default values to be `['tests']` and `['analyses']`
~-  Create a compatibility shim of some sort:~
     ~- Jake: "in the default case, we can check if any *.sql files exist inside tests, and if not fall back to looking in test (and emit a deprecation warning). This will be annoying for a hopefully tiny subset of the population who have a directory named tests with sql files in it."~ We don't want to do this
- Update the starter-project to set `['analyses']` for new projects going forward





Discussion:
How do we feel about the config for models being named 'source-paths'?  That's a bit confusing too since we have "models" and "sources" and "models" go in the "source-paths"...
I'm wondering whether checking a directory for SQL files is the way we want to go in a world in which file contents are not acquired by looking at a filesystem. The "frontend" processor has to know which files to send and therefore would need to do those kinds of checks. So there's a bit of a chicken-and-egg problem (something we'll have to deal with in a storage adapter world anyway).
> How do we feel about the config for models being named 'source-paths'? That's a bit confusing too since we have "models" and "sources" and "models" go in the "source-paths"...

@gshank You're absolutely right! See #1607, which is also on the v1.0 list. If you want to talk about that one at the same time as this issue, or consolidate the two into one effort, I think that would make a lot of sense.

> I'm wondering whether checking a directory for SQL files is the way we want to go in a world in which file contents are not acquired by looking at a filesystem.

This feels like a valuable discussion! We've talked in the past about using Jinja blocks to demarcate what code represents what thing, e.g. https://github.com/fishtown-analytics/dbt/issues/184. That was prominently featured on our v1.0 list, way back when. It's not something I'm convinced we need or want to do, but I think it raises fair questions for a world where dbt doesn't have to be so tightly coupled with a file system.
@jtcohen6 I am assigning this to @emmyoop to take a look at. Should the exit criteria be the 2 "should" points from above?

- [ ] Update the default values to be ['tests'] and ['analyses']
- [ ] Update the starter-project to set ['analyses'] for new projects going forward

@leahwicz Yes, that sounds exactly right to me! Because the `init` starter project sets explicit values for `analysis-paths` and `test-paths`, I don't believe these changes should be breaking for 99% of projects.

Resolving patch:
diff --git a/core/dbt/config/project.py b/core/dbt/config/project.py
--- a/core/dbt/config/project.py
+++ b/core/dbt/config/project.py
@@ -327,8 +327,8 @@ def create_project(self, rendered: RenderComponents) -> 'Project':
         source_paths: List[str] = value_or(cfg.source_paths, ['models'])
         macro_paths: List[str] = value_or(cfg.macro_paths, ['macros'])
         data_paths: List[str] = value_or(cfg.data_paths, ['data'])
-        test_paths: List[str] = value_or(cfg.test_paths, ['test'])
-        analysis_paths: List[str] = value_or(cfg.analysis_paths, [])
+        test_paths: List[str] = value_or(cfg.test_paths, ['tests'])
+        analysis_paths: List[str] = value_or(cfg.analysis_paths, ['analyses'])
         snapshot_paths: List[str] = value_or(cfg.snapshot_paths, ['snapshots'])
 
         all_source_paths: List[str] = _all_source_paths(


Test patch:
diff --git a/test/integration/006_simple_dependency_test/local_dependency/dbt_project.yml b/test/integration/006_simple_dependency_test/local_dependency/dbt_project.yml
--- a/test/integration/006_simple_dependency_test/local_dependency/dbt_project.yml
+++ b/test/integration/006_simple_dependency_test/local_dependency/dbt_project.yml
@@ -6,7 +6,7 @@ config-version: 2
 profile: 'default'
 
 source-paths: ["models"]
-analysis-paths: ["analysis"]
+analysis-paths: ["analyses"]
 test-paths: ["tests"]
 data-paths: ["data"]
 macro-paths: ["macros"]
diff --git a/test/integration/013_context_var_tests/first_dependency/dbt_project.yml b/test/integration/013_context_var_tests/first_dependency/dbt_project.yml
--- a/test/integration/013_context_var_tests/first_dependency/dbt_project.yml
+++ b/test/integration/013_context_var_tests/first_dependency/dbt_project.yml
@@ -6,7 +6,7 @@ config-version: 2
 profile: 'default'
 
 source-paths: ["models"]
-analysis-paths: ["analysis"]
+analysis-paths: ["analyses"]
 test-paths: ["tests"]
 data-paths: ["data"]
 macro-paths: ["macros"]
diff --git a/test/integration/019_analysis_tests/analysis/analysis.sql b/test/integration/019_analysis_tests/analyses/my_analysis.sql
similarity index 100%
rename from test/integration/019_analysis_tests/analysis/analysis.sql
rename to test/integration/019_analysis_tests/analyses/my_analysis.sql
diff --git a/test/integration/019_analysis_tests/analysis/raw_stuff.sql b/test/integration/019_analysis_tests/analyses/raw_stuff.sql
similarity index 100%
rename from test/integration/019_analysis_tests/analysis/raw_stuff.sql
rename to test/integration/019_analysis_tests/analyses/raw_stuff.sql
diff --git a/test/integration/019_analysis_tests/analysis/schema.yml b/test/integration/019_analysis_tests/analyses/schema.yml
similarity index 73%
rename from test/integration/019_analysis_tests/analysis/schema.yml
rename to test/integration/019_analysis_tests/analyses/schema.yml
--- a/test/integration/019_analysis_tests/analysis/schema.yml
+++ b/test/integration/019_analysis_tests/analyses/schema.yml
@@ -1,5 +1,5 @@
 version: 2
 
 analyses:
-  - name: analysis
+  - name: my_analysis
     description: "This is my analysis"
diff --git a/test/integration/019_analysis_tests/test_analyses.py b/test/integration/019_analysis_tests/test_analyses.py
--- a/test/integration/019_analysis_tests/test_analyses.py
+++ b/test/integration/019_analysis_tests/test_analyses.py
@@ -13,7 +13,7 @@ def models(self):
         return "models"
 
     def analysis_path(self):
-        return "analysis"
+        return "analyses"
 
     @property
     def project_config(self):
@@ -28,8 +28,8 @@ def assert_contents_equal(self, path, expected):
 
     @use_profile('postgres')
     def test_postgres_analyses(self):
-        compiled_analysis_path = os.path.normpath('target/compiled/test/analysis')
-        path_1 = os.path.join(compiled_analysis_path, 'analysis.sql')
+        compiled_analysis_path = os.path.normpath('target/compiled/test/analyses')
+        path_1 = os.path.join(compiled_analysis_path, 'my_analysis.sql')
         path_2 = os.path.join(compiled_analysis_path, 'raw_stuff.sql')
 
         self.run_dbt(['clean'])
@@ -37,7 +37,7 @@ def test_postgres_analyses(self):
         results = self.run_dbt(["compile"])
         self.assertEqual(len(results), 3)
         manifest = get_manifest()
-        analysis_id = 'analysis.test.analysis'
+        analysis_id = 'analysis.test.my_analysis'
         self.assertIn(analysis_id, manifest.nodes)
         node = manifest.nodes[analysis_id]
         self.assertEqual(node.description, 'This is my analysis')
diff --git a/test/integration/068_partial_parsing_tests/analysis/.gitignore b/test/integration/068_partial_parsing_tests/analyses/.gitignore
similarity index 100%
rename from test/integration/068_partial_parsing_tests/analysis/.gitignore
rename to test/integration/068_partial_parsing_tests/analyses/.gitignore
diff --git a/test/integration/068_partial_parsing_tests/local_dependency/dbt_project.yml b/test/integration/068_partial_parsing_tests/local_dependency/dbt_project.yml
--- a/test/integration/068_partial_parsing_tests/local_dependency/dbt_project.yml
+++ b/test/integration/068_partial_parsing_tests/local_dependency/dbt_project.yml
@@ -6,7 +6,7 @@ config-version: 2
 profile: 'default'
 
 source-paths: ["models"]
-analysis-paths: ["analysis"]
+analysis-paths: ["analyses"]
 test-paths: ["tests"]
 data-paths: ["data"]
 macro-paths: ["macros"]
diff --git a/test/integration/068_partial_parsing_tests/test_partial_parsing.py b/test/integration/068_partial_parsing_tests/test_partial_parsing.py
--- a/test/integration/068_partial_parsing_tests/test_partial_parsing.py
+++ b/test/integration/068_partial_parsing_tests/test_partial_parsing.py
@@ -224,7 +224,7 @@ def project_config(self):
             'data-paths': ['seed'],
             'test-paths': ['tests'],
             'macro-paths': ['macros-b'],
-            'analysis-paths': ['analysis'],
+            'analysis-paths': ['analyses'],
             'seeds': {
                 'quote_columns': False,
             },
@@ -248,8 +248,8 @@ def tearDown(self):
             os.remove(normalize('target/partial_parse.msgpack'))
         if os.path.exists(normalize('tests/my_test.sql')):
             os.remove(normalize('tests/my_test.sql'))
-        if os.path.exists(normalize('analysis/my_analysis.sql')):
-            os.remove(normalize('analysis/my_analysis.sql'))
+        if os.path.exists(normalize('analyses/my_analysis.sql')):
+            os.remove(normalize('analyses/my_analysis.sql'))
         if os.path.exists(normalize('macros-b/tests.sql')):
             os.remove(normalize('macros-b/tests.sql'))
 
@@ -345,7 +345,7 @@ def test_postgres_pp_sources(self):
         self.assertIn(test_id, manifest.nodes)
 
         # Add an analysis
-        shutil.copyfile('extra-files/my_analysis.sql', 'analysis/my_analysis.sql')
+        shutil.copyfile('extra-files/my_analysis.sql', 'analyses/my_analysis.sql')
         results = self.run_dbt(["--partial-parse", "run"])
         manifest = get_manifest()
 
@@ -356,7 +356,7 @@ def test_postgres_pp_sources(self):
         self.assertEqual(len(manifest.nodes), 9)
 
         # Remove analysis
-        os.remove(normalize('analysis/my_analysis.sql'))
+        os.remove(normalize('analyses/my_analysis.sql'))
         results = self.run_dbt(["--partial-parse", "run"])
         manifest = get_manifest()
         self.assertEqual(len(manifest.nodes), 8)
diff --git a/test/unit/test_config.py b/test/unit/test_config.py
--- a/test/unit/test_config.py
+++ b/test/unit/test_config.py
@@ -589,9 +589,9 @@ def test_defaults(self):
         self.assertEqual(project.source_paths, ['models'])
         self.assertEqual(project.macro_paths, ['macros'])
         self.assertEqual(project.data_paths, ['data'])
-        self.assertEqual(project.test_paths, ['test'])
-        self.assertEqual(project.analysis_paths, [])
-        self.assertEqual(project.docs_paths, ['models', 'data', 'snapshots', 'macros'])
+        self.assertEqual(project.test_paths, ['tests'])
+        self.assertEqual(project.analysis_paths, ['analyses'])
+        self.assertEqual(project.docs_paths, ['models', 'data', 'snapshots', 'analyses', 'macros'])
         self.assertEqual(project.asset_paths, [])
         self.assertEqual(project.target_path, 'target')
         self.assertEqual(project.clean_targets, ['target'])
@@ -624,7 +624,7 @@ def test_implicit_overrides(self):
             'target-path': 'other-target',
         })
         project = project_from_config_norender(self.default_project_data)
-        self.assertEqual(project.docs_paths, ['other-models', 'data', 'snapshots', 'macros'])
+        self.assertEqual(project.docs_paths, ['other-models', 'data', 'snapshots', 'analyses', 'macros'])
         self.assertEqual(project.clean_targets, ['other-target'])
 
     def test_hashed_name(self):
@@ -636,8 +636,8 @@ def test_all_overrides(self):
             'source-paths': ['other-models'],
             'macro-paths': ['other-macros'],
             'data-paths': ['other-data'],
-            'test-paths': ['other-test'],
-            'analysis-paths': ['analysis'],
+            'test-paths': ['other-tests'],
+            'analysis-paths': ['other-analyses'],
             'docs-paths': ['docs'],
             'asset-paths': ['other-assets'],
             'target-path': 'other-target',
@@ -706,8 +706,8 @@ def test_all_overrides(self):
         self.assertEqual(project.source_paths, ['other-models'])
         self.assertEqual(project.macro_paths, ['other-macros'])
         self.assertEqual(project.data_paths, ['other-data'])
-        self.assertEqual(project.test_paths, ['other-test'])
-        self.assertEqual(project.analysis_paths, ['analysis'])
+        self.assertEqual(project.test_paths, ['other-tests'])
+        self.assertEqual(project.analysis_paths, ['other-analyses'])
         self.assertEqual(project.docs_paths, ['docs'])
         self.assertEqual(project.asset_paths, ['other-assets'])
         self.assertEqual(project.target_path, 'other-target')
@@ -1201,9 +1201,9 @@ def test_from_args(self):
         self.assertEqual(config.source_paths, ['models'])
         self.assertEqual(config.macro_paths, ['macros'])
         self.assertEqual(config.data_paths, ['data'])
-        self.assertEqual(config.test_paths, ['test'])
-        self.assertEqual(config.analysis_paths, [])
-        self.assertEqual(config.docs_paths, ['models', 'data', 'snapshots', 'macros'])
+        self.assertEqual(config.test_paths, ['tests'])
+        self.assertEqual(config.analysis_paths, ['analyses'])
+        self.assertEqual(config.docs_paths, ['models', 'data', 'snapshots', 'analyses', 'macros'])
         self.assertEqual(config.asset_paths, [])
         self.assertEqual(config.target_path, 'target')
         self.assertEqual(config.clean_targets, ['target'])