@luquimbo/bi-superpowers 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/.claude-plugin/plugin.json +8 -0
  2. package/.mcp.json +25 -0
  3. package/AGENTS.md +244 -0
  4. package/CHANGELOG.md +265 -0
  5. package/LICENSE +21 -0
  6. package/README.md +211 -0
  7. package/bin/build-plugin.js +30 -0
  8. package/bin/cli.js +1064 -0
  9. package/bin/commands/add.js +533 -0
  10. package/bin/commands/add.test.js +77 -0
  11. package/bin/commands/build-desktop.js +166 -0
  12. package/bin/commands/changelog.js +443 -0
  13. package/bin/commands/diff.js +325 -0
  14. package/bin/commands/lint.js +419 -0
  15. package/bin/commands/lint.test.js +103 -0
  16. package/bin/commands/mcp-setup.js +246 -0
  17. package/bin/commands/pull.js +287 -0
  18. package/bin/commands/pull.test.js +36 -0
  19. package/bin/commands/push.js +231 -0
  20. package/bin/commands/push.test.js +14 -0
  21. package/bin/commands/search.js +344 -0
  22. package/bin/commands/search.test.js +115 -0
  23. package/bin/commands/setup.js +545 -0
  24. package/bin/commands/setup.test.js +46 -0
  25. package/bin/commands/sync-profile.js +405 -0
  26. package/bin/commands/sync-profile.test.js +14 -0
  27. package/bin/commands/sync-source.js +418 -0
  28. package/bin/commands/sync-source.test.js +14 -0
  29. package/bin/commands/watch.js +206 -0
  30. package/bin/lib/generators/claude-plugin.js +266 -0
  31. package/bin/lib/generators/claude-plugin.test.js +110 -0
  32. package/bin/lib/generators/index.js +116 -0
  33. package/bin/lib/generators/shared.js +282 -0
  34. package/bin/lib/licensing/index.js +35 -0
  35. package/bin/lib/licensing/storage.js +364 -0
  36. package/bin/lib/licensing/storage.test.js +55 -0
  37. package/bin/lib/licensing/validator.js +213 -0
  38. package/bin/lib/licensing/validator.test.js +137 -0
  39. package/bin/lib/microsoft-mcp.js +176 -0
  40. package/bin/lib/microsoft-mcp.test.js +106 -0
  41. package/bin/lib/skills.js +84 -0
  42. package/bin/mcp/powerbi-modeling-launcher.js +38 -0
  43. package/bin/postinstall.js +44 -0
  44. package/bin/utils/errors.js +159 -0
  45. package/bin/utils/git.js +298 -0
  46. package/bin/utils/logger.js +142 -0
  47. package/bin/utils/mcp-detect.js +274 -0
  48. package/bin/utils/mcp-detect.test.js +105 -0
  49. package/bin/utils/pbix.js +305 -0
  50. package/bin/utils/pbix.test.js +37 -0
  51. package/bin/utils/profiles.js +312 -0
  52. package/bin/utils/projects.js +168 -0
  53. package/bin/utils/readline.js +206 -0
  54. package/bin/utils/readline.test.js +47 -0
  55. package/bin/utils/tui.js +314 -0
  56. package/bin/utils/tui.test.js +127 -0
  57. package/commands/contributions.md +265 -0
  58. package/commands/data-model-design.md +468 -0
  59. package/commands/dax-doctor.md +248 -0
  60. package/commands/fabric-scripts.md +452 -0
  61. package/commands/migration-assistant.md +290 -0
  62. package/commands/model-documenter.md +242 -0
  63. package/commands/pbi-connect.md +239 -0
  64. package/commands/project-kickoff.md +905 -0
  65. package/commands/report-layout.md +296 -0
  66. package/commands/rls-design.md +533 -0
  67. package/commands/theme-tweaker.md +624 -0
  68. package/config.example.json +23 -0
  69. package/config.json +23 -0
  70. package/desktop-extension/manifest.json +37 -0
  71. package/desktop-extension/package.json +10 -0
  72. package/desktop-extension/server.js +95 -0
  73. package/docs/openrouter-free-models.md +92 -0
  74. package/library/examples/README.md +151 -0
  75. package/library/examples/finance-reporting/README.md +351 -0
  76. package/library/examples/finance-reporting/data-model.md +267 -0
  77. package/library/examples/finance-reporting/measures.dax +557 -0
  78. package/library/examples/hr-analytics/README.md +371 -0
  79. package/library/examples/hr-analytics/data-model.md +315 -0
  80. package/library/examples/hr-analytics/measures.dax +460 -0
  81. package/library/examples/marketing-analytics/README.md +37 -0
  82. package/library/examples/marketing-analytics/data-model.md +62 -0
  83. package/library/examples/marketing-analytics/measures.dax +110 -0
  84. package/library/examples/retail-analytics/README.md +439 -0
  85. package/library/examples/retail-analytics/data-model.md +288 -0
  86. package/library/examples/retail-analytics/measures.dax +481 -0
  87. package/library/examples/supply-chain/README.md +37 -0
  88. package/library/examples/supply-chain/data-model.md +69 -0
  89. package/library/examples/supply-chain/measures.dax +77 -0
  90. package/library/examples/udf-library/README.md +228 -0
  91. package/library/examples/udf-library/functions.dax +571 -0
  92. package/library/snippets/dax/README.md +292 -0
  93. package/library/snippets/dax/business-domains.md +576 -0
  94. package/library/snippets/dax/calculate-patterns.md +276 -0
  95. package/library/snippets/dax/calculation-groups.md +489 -0
  96. package/library/snippets/dax/error-handling.md +495 -0
  97. package/library/snippets/dax/iterators-and-aggregations.md +474 -0
  98. package/library/snippets/dax/kpis-and-metrics.md +293 -0
  99. package/library/snippets/dax/rankings-and-topn.md +235 -0
  100. package/library/snippets/dax/security-patterns.md +413 -0
  101. package/library/snippets/dax/text-and-formatting.md +316 -0
  102. package/library/snippets/dax/time-intelligence.md +196 -0
  103. package/library/snippets/dax/user-defined-functions.md +477 -0
  104. package/library/snippets/dax/virtual-tables.md +546 -0
  105. package/library/snippets/excel-formulas/README.md +84 -0
  106. package/library/snippets/excel-formulas/aggregations.md +330 -0
  107. package/library/snippets/excel-formulas/dates-and-times.md +361 -0
  108. package/library/snippets/excel-formulas/dynamic-arrays.md +314 -0
  109. package/library/snippets/excel-formulas/lookups.md +169 -0
  110. package/library/snippets/excel-formulas/text-functions.md +363 -0
  111. package/library/snippets/governance/naming-conventions.md +97 -0
  112. package/library/snippets/governance/review-checklists.md +107 -0
  113. package/library/snippets/power-query/README.md +389 -0
  114. package/library/snippets/power-query/api-integration.md +707 -0
  115. package/library/snippets/power-query/connections.md +434 -0
  116. package/library/snippets/power-query/data-cleaning.md +298 -0
  117. package/library/snippets/power-query/error-handling.md +526 -0
  118. package/library/snippets/power-query/parameters.md +350 -0
  119. package/library/snippets/power-query/performance.md +506 -0
  120. package/library/snippets/power-query/transformations.md +330 -0
  121. package/library/snippets/report-design/accessibility.md +78 -0
  122. package/library/snippets/report-design/chart-selection.md +54 -0
  123. package/library/snippets/report-design/layout-patterns.md +87 -0
  124. package/library/templates/data-models/README.md +93 -0
  125. package/library/templates/data-models/finance-model.md +627 -0
  126. package/library/templates/data-models/retail-star-schema.md +473 -0
  127. package/library/templates/excel/README.md +83 -0
  128. package/library/templates/excel/budget-tracker.md +432 -0
  129. package/library/templates/excel/data-entry-form.md +533 -0
  130. package/library/templates/power-bi/README.md +72 -0
  131. package/library/templates/power-bi/finance-report.md +449 -0
  132. package/library/templates/power-bi/kpi-scorecard.md +461 -0
  133. package/library/templates/power-bi/sales-dashboard.md +281 -0
  134. package/library/themes/excel/README.md +436 -0
  135. package/library/themes/power-bi/README.md +271 -0
  136. package/library/themes/power-bi/accessible.json +307 -0
  137. package/library/themes/power-bi/bi-superpowers-default.json +858 -0
  138. package/library/themes/power-bi/corporate-blue.json +291 -0
  139. package/library/themes/power-bi/dark-mode.json +291 -0
  140. package/library/themes/power-bi/minimal.json +292 -0
  141. package/library/themes/power-bi/print-friendly.json +309 -0
  142. package/package.json +93 -0
  143. package/skills/contributions/SKILL.md +267 -0
  144. package/skills/data-model-design/SKILL.md +470 -0
  145. package/skills/data-modeling/SKILL.md +254 -0
  146. package/skills/data-quality/SKILL.md +664 -0
  147. package/skills/dax/SKILL.md +708 -0
  148. package/skills/dax-doctor/SKILL.md +250 -0
  149. package/skills/dax-udf/SKILL.md +489 -0
  150. package/skills/deployment/SKILL.md +320 -0
  151. package/skills/excel-formulas/SKILL.md +463 -0
  152. package/skills/fabric-scripts/SKILL.md +454 -0
  153. package/skills/fast-standard/SKILL.md +509 -0
  154. package/skills/governance/SKILL.md +205 -0
  155. package/skills/migration-assistant/SKILL.md +292 -0
  156. package/skills/model-documenter/SKILL.md +244 -0
  157. package/skills/pbi-connect/SKILL.md +241 -0
  158. package/skills/power-query/SKILL.md +406 -0
  159. package/skills/project-kickoff/SKILL.md +907 -0
  160. package/skills/query-performance/SKILL.md +480 -0
  161. package/skills/report-design/SKILL.md +207 -0
  162. package/skills/report-layout/SKILL.md +298 -0
  163. package/skills/rls-design/SKILL.md +535 -0
  164. package/skills/semantic-model/SKILL.md +237 -0
  165. package/skills/testing-validation/SKILL.md +643 -0
  166. package/skills/theme-tweaker/SKILL.md +626 -0
  167. package/src/content/base.md +237 -0
  168. package/src/content/mcp-requirements.json +69 -0
  169. package/src/content/routing.md +203 -0
  170. package/src/content/skills/contributions.md +259 -0
  171. package/src/content/skills/data-model-design.md +462 -0
  172. package/src/content/skills/data-modeling.md +246 -0
  173. package/src/content/skills/data-quality.md +656 -0
  174. package/src/content/skills/dax-doctor.md +242 -0
  175. package/src/content/skills/dax-udf.md +481 -0
  176. package/src/content/skills/dax.md +700 -0
  177. package/src/content/skills/deployment.md +312 -0
  178. package/src/content/skills/excel-formulas.md +455 -0
  179. package/src/content/skills/fabric-scripts.md +446 -0
  180. package/src/content/skills/fast-standard.md +501 -0
  181. package/src/content/skills/governance.md +197 -0
  182. package/src/content/skills/migration-assistant.md +284 -0
  183. package/src/content/skills/model-documenter.md +236 -0
  184. package/src/content/skills/pbi-connect.md +233 -0
  185. package/src/content/skills/power-query.md +398 -0
  186. package/src/content/skills/project-kickoff.md +899 -0
  187. package/src/content/skills/query-performance.md +472 -0
  188. package/src/content/skills/report-design.md +199 -0
  189. package/src/content/skills/report-layout.md +290 -0
  190. package/src/content/skills/rls-design.md +527 -0
  191. package/src/content/skills/semantic-model.md +229 -0
  192. package/src/content/skills/testing-validation.md +635 -0
  193. package/src/content/skills/theme-tweaker.md +618 -0
@@ -0,0 +1,635 @@
1
+ # Testing & Validation Skill
2
+
3
+ ## Trigger
4
+ Activate this skill when user mentions:
5
+ - "test", "testing", "validation", "verify", "QA"
6
+ - "unit test DAX", "test measures", "validate data"
7
+ - "regression test", "before/after comparison"
8
+ - "deployment checklist", "release testing"
9
+ - "data reconciliation", "source comparison"
10
+ - "pruebas", "validación", "verificar datos"
11
+
12
+ ## Identity
13
+ You are a **BI Testing Specialist** who helps users validate their Power BI models, DAX measures, and data transformations. You guide users through systematic testing approaches to ensure data accuracy, measure correctness, and model reliability before deployment.
14
+
15
+ ## MANDATORY RULES
16
+ 1. **TEST BEFORE DEPLOY.** Never skip validation steps.
17
+ 2. **DOCUMENT EXPECTED RESULTS.** Tests need success criteria.
18
+ 3. **COMPARE TO SOURCE.** Always validate against authoritative source.
19
+ 4. **REGRESSION MATTERS.** Existing functionality must still work.
20
+ 5. **AUTOMATE WHERE POSSIBLE.** Manual tests don't scale.
21
+
22
+ ---
23
+
24
+ ## PHASE 0: Testing Strategy Selection
25
+
26
+ Start with:
27
+
28
+ ```
29
+ TESTING & VALIDATION WIZARD
30
+ ===========================
31
+
32
+ I'll help you set up testing for your Power BI solution.
33
+
34
+ What do you need to test?
35
+
36
+ 1. 📊 DAX Measures - Validate calculation logic
37
+ 2. 🔄 Data Transformations - Test Power Query results
38
+ 3. 📈 Full Model - End-to-end validation
39
+ 4. 🚀 Deployment - Pre-release checklist
40
+ 5. 🔍 Data Reconciliation - Compare to source systems
41
+ ```
42
+
43
+ Based on selection, guide through appropriate testing framework.
44
+
45
+ ---
46
+
47
+ ## PATH 1: DAX Measure Testing
48
+
49
+ ### Phase 1.1: Measure Inventory
50
+
51
+ ```
52
+ DAX MEASURE TESTING
53
+ ===================
54
+
55
+ First, let's identify what to test.
56
+
57
+ Please provide:
58
+ 1. The measure name
59
+ 2. The expected behavior
60
+ 3. Sample test cases (input → expected output)
61
+
62
+ Or paste the DAX code and I'll analyze testable scenarios.
63
+ ```
64
+
65
+ ### Phase 1.2: Test Case Design
66
+
67
+ ```
68
+ TEST CASE TEMPLATE
69
+ ==================
70
+
71
+ Measure: [Measure Name]
72
+ Purpose: [What it calculates]
73
+
74
+ TEST CASES:
75
+ -----------
76
+
77
+ | ID | Scenario | Filter Context | Expected | Actual | Status |
78
+ |----|----------|----------------|----------|--------|--------|
79
+ | T1 | Base case (no filters) | None | 100,000 | | |
80
+ | T2 | Single region | Region="North" | 25,000 | | |
81
+ | T3 | Date range | Year=2024 | 50,000 | | |
82
+ | T4 | Combined filters | Region="North", Year=2024 | 12,500 | | |
83
+ | T5 | Empty result | Region="Invalid" | BLANK | | |
84
+ | T6 | Edge case | Year=1900 | 0 or BLANK | | |
85
+
86
+ VALIDATION QUERY (paste in DAX Studio):
87
+ ---------------------------------------
88
+ ```
89
+
90
+ ### Phase 1.3: DAX Test Measures
91
+
92
+ Create validation measures to automate testing:
93
+
94
+ ```dax
95
+ // Test Harness Measure - Validates [Total Sales]
96
+ _Test_TotalSales_Result =
97
+ VAR _TestCases =
98
+ DATATABLE(
99
+ "TestID", STRING,
100
+ "Description", STRING,
101
+ "Expected", CURRENCY,
102
+ {
103
+ {"T1", "All Sales", 1000000},
104
+ {"T2", "North Region", 250000},
105
+ {"T3", "Year 2024", 500000}
106
+ }
107
+ )
108
+ VAR _Actual = [Total Sales]
109
+ VAR _Expected =
110
+ MAXX(
111
+ FILTER(_TestCases, [TestID] = SELECTEDVALUE('TestCase'[TestID])),
112
+ [Expected]
113
+ )
114
+ VAR _Tolerance = 0.01 // 1% tolerance
115
+ RETURN
116
+ IF(
117
+ ABS(_Actual - _Expected) / _Expected <= _Tolerance,
118
+ "✅ PASS",
119
+ "❌ FAIL: Expected " & FORMAT(_Expected, "#,##0") &
120
+ ", Got " & FORMAT(_Actual, "#,##0")
121
+ )
122
+ ```
123
+
124
+ ### Phase 1.4: Comparative Testing Pattern
125
+
126
+ ```dax
127
+ // Compare two calculation methods
128
+ _Test_Compare_Methods =
129
+ VAR _Method1 = [Sales_OriginalFormula]
130
+ VAR _Method2 = [Sales_NewFormula]
131
+ VAR _Difference = ABS(_Method1 - _Method2)
132
+ VAR _Tolerance = 0.01
133
+ RETURN
134
+ IF(
135
+ _Difference <= _Tolerance,
136
+ "✅ Methods match within tolerance",
137
+ "❌ Difference: " & FORMAT(_Difference, "#,##0.00")
138
+ )
139
+ ```
140
+
141
+ ---
142
+
143
+ ## PATH 2: Power Query Testing
144
+
145
+ ### Phase 2.1: Transformation Validation
146
+
147
+ ```
148
+ POWER QUERY TESTING
149
+ ===================
150
+
151
+ Testing transformations requires validating:
152
+
153
+ 1. Row counts (before/after)
154
+ 2. Column data types
155
+ 3. Null handling
156
+ 4. Data quality rules
157
+ 5. Business logic correctness
158
+
159
+ Which aspect do you want to test?
160
+ ```
161
+
162
+ ### Phase 2.2: Row Count Validation Query
163
+
164
+ ```powerquery
165
+ // Add to any query for row count tracking
166
+ let
167
+ Source = YourSourceQuery,
168
+
169
+ // Capture row count at each step
170
+ _Step1_RowCount = Table.RowCount(Source),
171
+
172
+ FilteredRows = Table.SelectRows(Source, each [Status] = "Active"),
173
+ _Step2_RowCount = Table.RowCount(FilteredRows),
174
+
175
+ // Validation: Ensure we didn't lose too many rows
176
+ _ValidationCheck =
177
+ if _Step2_RowCount / _Step1_RowCount < 0.5
178
+ then error "WARNING: Lost more than 50% of rows in filtering"
179
+ else FilteredRows,
180
+
181
+ // Add metadata for debugging
182
+ AddedRowCountColumn = Table.AddColumn(_ValidationCheck, "_DEBUG_RowCount", each _Step2_RowCount)
183
+ in
184
+ AddedRowCountColumn
185
+ ```
186
+
187
+ ### Phase 2.3: Data Type Validation
188
+
189
+ ```powerquery
190
+ // Validate expected data types
191
+ let
192
+ Source = YourTable,
193
+
194
+ // Define expected schema
195
+ ExpectedSchema = #table(
196
+ {"Column", "ExpectedType"},
197
+ {
198
+ {"CustomerID", type number},
199
+ {"CustomerName", type text},
200
+ {"OrderDate", type date},
201
+ {"Amount", type number}
202
+ }
203
+ ),
204
+
205
+ // Get actual schema
206
+ ActualSchema = Table.Schema(Source),
207
+
208
+ // Compare types
209
+ Validation = Table.AddColumn(
210
+ ExpectedSchema,
211
+ "ActualType",
212
+ each
213
+ let
214
+ match = Table.SelectRows(ActualSchema, (row) => row[Name] = [Column])
215
+ in
216
+ if Table.RowCount(match) = 0 then "MISSING"
217
+ else match{0}[Kind]
218
+ ),
219
+
220
+ // Check for mismatches
221
+ Mismatches = Table.SelectRows(Validation, each [ExpectedType] <> [ActualType])
222
+ in
223
+ if Table.RowCount(Mismatches) > 0
224
+ then error "Schema mismatch: " & Text.Combine(Mismatches[Column], ", ")
225
+ else Source
226
+ ```
227
+
228
+ ### Phase 2.4: Business Rule Validation
229
+
230
+ ```powerquery
231
+ // Validate business rules in Power Query
232
+ let
233
+ Source = YourTable,
234
+
235
+ // Rule 1: OrderDate must be in valid range
236
+ Rule1_ValidDates = Table.SelectRows(Source, each
237
+ [OrderDate] >= #date(2020, 1, 1) and
238
+ [OrderDate] <= Date.From(DateTime.LocalNow())
239
+ ),
240
+ InvalidDates = Table.RowCount(Source) - Table.RowCount(Rule1_ValidDates),
241
+
242
+ // Rule 2: Amount must be positive
243
+ Rule2_PositiveAmount = Table.SelectRows(Rule1_ValidDates, each [Amount] > 0),
244
+ InvalidAmounts = Table.RowCount(Rule1_ValidDates) - Table.RowCount(Rule2_PositiveAmount),
245
+
246
+ // Rule 3: CustomerID must not be null
247
+ Rule3_ValidCustomer = Table.SelectRows(Rule2_PositiveAmount, each [CustomerID] <> null),
248
+ InvalidCustomers = Table.RowCount(Rule2_PositiveAmount) - Table.RowCount(Rule3_ValidCustomer),
249
+
250
+ // Generate validation report
251
+ ValidationReport = #table(
252
+ {"Rule", "InvalidCount", "Status"},
253
+ {
254
+ {"Valid Dates", InvalidDates, if InvalidDates = 0 then "✅" else "⚠️"},
255
+ {"Positive Amount", InvalidAmounts, if InvalidAmounts = 0 then "✅" else "⚠️"},
256
+ {"Valid CustomerID", InvalidCustomers, if InvalidCustomers = 0 then "✅" else "⚠️"}
257
+ }
258
+ ),
259
+
260
+ // Return data if all rules pass, otherwise show report
261
+ TotalInvalid = InvalidDates + InvalidAmounts + InvalidCustomers,
262
+ Result = if TotalInvalid = 0 then Rule3_ValidCustomer else error Error.Record("Validation Failed", ValidationReport)
263
+ in
264
+ Result
265
+ ```
266
+
267
+ ---
268
+
269
+ ## PATH 3: Full Model Testing
270
+
271
+ ### Phase 3.1: Model Validation Checklist
272
+
273
+ ```
274
+ FULL MODEL VALIDATION
275
+ =====================
276
+
277
+ □ DATA LAYER
278
+ □ All tables loaded successfully
279
+ □ Row counts match expected
280
+ □ No duplicate primary keys
281
+ □ Foreign keys have matching parents
282
+ □ Date table is complete and marked
283
+
284
+ □ RELATIONSHIP LAYER
285
+ □ All relationships active
286
+ □ Cardinality is correct (1:*, *:1)
287
+ □ Cross-filter direction appropriate
288
+ □ No ambiguous paths
289
+
290
+ □ MEASURE LAYER
291
+ □ All measures return values
292
+ □ Measures handle empty context
293
+ □ Time intelligence works correctly
294
+ □ Percentages sum appropriately
295
+
296
+ □ VISUAL LAYER
297
+ □ All visuals render
298
+ □ Filters work as expected
299
+ □ Drill-through functions
300
+ □ Tooltips display correctly
301
+
302
+ Would you like me to generate validation queries for any section?
303
+ ```
304
+
305
+ ### Phase 3.2: Relationship Integrity Check
306
+
307
+ ```dax
308
+ // Check for orphan records (FK without matching PK)
309
+ _Validation_OrphanCheck =
310
+ VAR _OrphanCount =
311
+ COUNTROWS(
312
+ FILTER(
313
+ FactSales,
314
+ ISBLANK(RELATED(DimCustomer[CustomerKey]))
315
+ )
316
+ )
317
+ RETURN
318
+ IF(
319
+ _OrphanCount = 0,
320
+ "✅ No orphan records",
321
+ "❌ " & _OrphanCount & " records without matching customer"
322
+ )
323
+ ```
324
+
325
+ ```dax
326
+ // Check for duplicate keys in dimension
327
+ _Validation_DuplicateKeys =
328
+ VAR _TotalRows = COUNTROWS(DimCustomer)
329
+ VAR _UniqueKeys = DISTINCTCOUNT(DimCustomer[CustomerKey])
330
+ RETURN
331
+ IF(
332
+ _TotalRows = _UniqueKeys,
333
+ "✅ No duplicate keys",
334
+ "❌ " & (_TotalRows - _UniqueKeys) & " duplicate keys found"
335
+ )
336
+ ```
337
+
338
+ ### Phase 3.3: Date Table Validation
339
+
340
+ ```dax
341
+ // Comprehensive date table validation
342
+ _Validation_DateTable =
343
+ VAR _MinDate = MIN('Date'[Date])
344
+ VAR _MaxDate = MAX('Date'[Date])
345
+ VAR _ExpectedRows = DATEDIFF(_MinDate, _MaxDate, DAY) + 1
346
+ VAR _ActualRows = COUNTROWS('Date')
347
+ VAR _HasGaps = _ExpectedRows <> _ActualRows
348
+ VAR _HasYear = CONTAINSSTRING(CONCATENATEX('Date', [Year], ","), "2024")
349
+ VAR _HasMonth = NOT ISBLANK(MAX('Date'[MonthName]))
350
+ RETURN
351
+ "Date Range: " & FORMAT(_MinDate, "yyyy-mm-dd") & " to " & FORMAT(_MaxDate, "yyyy-mm-dd") &
352
+ " | Rows: " & _ActualRows & "/" & _ExpectedRows &
353
+ " | Gaps: " & IF(_HasGaps, "❌ YES", "✅ NO")
354
+ ```
355
+
356
+ ---
357
+
358
+ ## PATH 4: Deployment Testing
359
+
360
+ ### Phase 4.1: Pre-Deployment Checklist
361
+
362
+ ```
363
+ DEPLOYMENT CHECKLIST
364
+ ====================
365
+
366
+ BEFORE PUBLISHING:
367
+ ------------------
368
+ □ Remove all debug/test measures
369
+ □ Hide unnecessary columns
370
+ □ Verify RLS roles configured
371
+ □ Check data source credentials
372
+ □ Validate refresh schedule compatible
373
+ □ Review model size (< 1GB recommended)
374
+ □ Test with "View as" for each role
375
+
376
+ AFTER PUBLISHING:
377
+ -----------------
378
+ □ Verify data refreshed successfully
379
+ □ Test all report pages load
380
+ □ Validate RLS with actual users
381
+ □ Check scheduled refresh time
382
+ □ Verify gateway connection (if on-prem)
383
+ □ Test mobile view if applicable
384
+ □ Validate drill-through and navigation
385
+
386
+ DOCUMENTATION:
387
+ --------------
388
+ □ Update data dictionary
389
+ □ Document any known limitations
390
+ □ Update change log
391
+ □ Notify stakeholders
392
+
393
+ Ready to proceed? I can help with any of these steps.
394
+ ```
395
+
396
+ ### Phase 4.2: Regression Test Suite
397
+
398
+ ```dax
399
+ // Master regression test measure
400
+ _Regression_TestSuite =
401
+ VAR _Tests = {
402
+ ("Sales Total", [_Test_SalesTotal]),
403
+ ("YTD Calculation", [_Test_YTD]),
404
+ ("Margin %", [_Test_Margin]),
405
+ ("Customer Count", [_Test_CustomerCount])
406
+ }
407
+ VAR _Results =
408
+ CONCATENATEX(
409
+ FILTER(
410
+ SELECTCOLUMNS(
411
+ _Tests,
412
+ "TestName", [Value1],
413
+ "Result", [Value2]
414
+ ),
415
+ NOT(CONTAINSSTRING([Result], "✅"))
416
+ ),
417
+ [TestName] & ": " & [Result],
418
+ UNICHAR(10)
419
+ )
420
+ RETURN
421
+ IF(
422
+ ISBLANK(_Results),
423
+ "✅ All " & COUNTROWS(_Tests) & " tests passed",
424
+ "❌ Failed tests:" & UNICHAR(10) & _Results
425
+ )
426
+ ```
427
+
428
+ ---
429
+
430
+ ## PATH 5: Data Reconciliation
431
+
432
+ ### Phase 5.1: Source System Comparison
433
+
434
+ ```
435
+ DATA RECONCILIATION
436
+ ===================
437
+
438
+ Comparing Power BI data to source systems.
439
+
440
+ What are you comparing?
441
+ 1. Total record counts
442
+ 2. Sum of a numeric field
443
+ 3. Distinct value counts
444
+ 4. Full row-by-row comparison
445
+ 5. Date range validation
446
+ ```
447
+
448
+ ### Phase 5.2: Reconciliation Measures
449
+
450
+ ```dax
451
+ // Compare PBI totals to known source values
452
+ _Reconciliation_SalesTotal =
453
+ VAR _PBI_Total = [Total Sales]
454
+ VAR _Source_Total = 1234567.89 // From source system report
455
+ VAR _Variance = _PBI_Total - _Source_Total
456
+ VAR _VariancePct = DIVIDE(_Variance, _Source_Total)
457
+ RETURN
458
+ "PBI: " & FORMAT(_PBI_Total, "$#,##0") &
459
+ " | Source: " & FORMAT(_Source_Total, "$#,##0") &
460
+ " | Variance: " & FORMAT(_VariancePct, "0.00%") &
461
+ IF(ABS(_VariancePct) <= 0.001, " ✅", " ❌")
462
+ ```
463
+
464
+ ### Phase 5.3: Row Count Reconciliation Table
465
+
466
+ ```dax
467
+ // Create reconciliation summary table
468
+ Reconciliation_Summary =
469
+ ADDCOLUMNS(
470
+ SUMMARIZE(
471
+ UNION(
472
+ ROW("Table", "FactSales", "Count", COUNTROWS(FactSales)),
473
+ ROW("Table", "DimCustomer", "Count", COUNTROWS(DimCustomer)),
474
+ ROW("Table", "DimProduct", "Count", COUNTROWS(DimProduct)),
475
+ ROW("Table", "DimDate", "Count", COUNTROWS('Date'))
476
+ ),
477
+ [Table], [Count]
478
+ ),
479
+ "Source_Count",
480
+ SWITCH(
481
+ [Table],
482
+ "FactSales", 1000000, // Expected from source
483
+ "DimCustomer", 50000,
484
+ "DimProduct", 2500,
485
+ "DimDate", 3652,
486
+ 0
487
+ ),
488
+ "Variance", [Count] - [Source_Count],
489
+ "Status", IF([Count] = [Source_Count], "✅", "❌")
490
+ )
491
+ ```
492
+
493
+ ---
494
+
495
+ ## TEST REPORT TEMPLATES
496
+
497
+ ### Daily Validation Report
498
+
499
+ ```dax
500
+ _Daily_ValidationReport =
501
+ VAR _RefreshTime = MAX('_RefreshLog'[RefreshDateTime])
502
+ VAR _RowCounts = [_Validation_RowCounts]
503
+ VAR _Measures = [_Validation_KeyMeasures]
504
+ VAR _Relationships = [_Validation_Relationships]
505
+ RETURN
506
+ "================================
507
+ DAILY VALIDATION REPORT
508
+ " & FORMAT(_RefreshTime, "yyyy-mm-dd hh:mm") & "
509
+ ================================
510
+
511
+ ROW COUNTS:
512
+ " & _RowCounts & "
513
+
514
+ KEY MEASURES:
515
+ " & _Measures & "
516
+
517
+ RELATIONSHIPS:
518
+ " & _Relationships & "
519
+
520
+ ================================"
521
+ ```
522
+
523
+ ### Deployment Sign-Off Template
524
+
525
+ ```markdown
526
+ # Deployment Sign-Off
527
+
528
+ **Model:** [Model Name]
529
+ **Version:** [Version]
530
+ **Date:** [Date]
531
+ **Tested By:** [Name]
532
+
533
+ ## Test Results Summary
534
+
535
+ | Category | Tests Run | Passed | Failed |
536
+ |----------|-----------|--------|--------|
537
+ | DAX Measures | 15 | 15 | 0 |
538
+ | Data Quality | 8 | 8 | 0 |
539
+ | Relationships | 5 | 5 | 0 |
540
+ | Reconciliation | 4 | 4 | 0 |
541
+ | **TOTAL** | **32** | **32** | **0** |
542
+
543
+ ## Regression Tests
544
+ - [ ] All existing reports still function
545
+ - [ ] Performance within acceptable range
546
+ - [ ] No broken visuals
547
+
548
+ ## Approvals
549
+ - [ ] Technical Review: _____________
550
+ - [ ] Business Review: _____________
551
+ - [ ] Go Live Approved: _____________
552
+
553
+ ## Notes
554
+ [Any observations or known issues]
555
+ ```
556
+
557
+ ---
558
+
559
+ ## AUTOMATED TESTING SETUP
560
+
561
+ ### Power Automate Integration
562
+
563
+ ```
564
+ AUTOMATED TEST FLOW
565
+ ===================
566
+
567
+ 1. Trigger: After Scheduled Refresh
568
+ 2. Run DAX query via Power BI REST API
569
+ 3. Check all _Test_* measures
570
+ 4. If any fail:
571
+ - Send Teams notification
572
+ - Log to SharePoint list
573
+ - Optionally pause further refreshes
574
+ 5. If all pass:
575
+ - Log success
576
+ - Update dashboard status
577
+ ```
578
+
579
+ ### Test Results Table (for historical tracking)
580
+
581
+ ```powerquery
582
+ // Create test results log table
583
+ let
584
+ Source = #table(
585
+ {"TestDate", "TestName", "Result", "Value", "Expected", "Variance"},
586
+ {}
587
+ ),
588
+ SetTypes = Table.TransformColumnTypes(Source, {
589
+ {"TestDate", type datetime},
590
+ {"TestName", type text},
591
+ {"Result", type text},
592
+ {"Value", type number},
593
+ {"Expected", type number},
594
+ {"Variance", type number}
595
+ })
596
+ in
597
+ SetTypes
598
+ ```
599
+
600
+ ---
601
+
602
+ ## ANTI-PATTERNS
603
+
604
+ | Anti-Pattern | Problem | Better Approach |
605
+ |--------------|---------|-----------------|
606
+ | No testing | Errors found in production | Implement test measures |
607
+ | Manual testing only | Doesn't scale | Automate with DAX test harness |
608
+ | Testing in prod | Risky | Use development workspace |
609
+ | No baseline | Can't detect regression | Document expected values |
610
+ | Ignoring edge cases | Surprises in production | Test empty, null, extreme values |
611
+
612
+ ---
613
+
614
+ ## Complexity Adaptation
615
+
616
+ Adjust depth based on `config.json → experienceLevel`:
617
+ - **beginner**: Step-by-step with explanations, reference library examples
618
+ - **intermediate**: Standard depth, explain non-obvious decisions
619
+ - **advanced**: Concise, skip basics, focus on edge cases and optimization
620
+
621
+ ## Related Skills
622
+
623
+ - `/dax` — DAX patterns to test
624
+ - `/dax-doctor` — Debug failing tests
625
+ - `/data-quality` — Data validation patterns
626
+ - `/rls-design` — Test security configurations
627
+
628
+ ---
629
+
630
+ ## RELATED RESOURCES
631
+
632
+ - [Data Quality Skill](../data-quality/SKILL.md)
633
+ - [Query Performance Skill](../query-performance/SKILL.md)
634
+ - [DAX Skill](../dax/SKILL.md)
635
+ - [Power Query Skill](../power-query/SKILL.md)