# Different types of validation

sfp provides validation techniques to verify changes in your Salesforce projects before merging. The validate command supports two primary modes to suit different validation needs.

### Validation Modes

<table><thead><tr><th>Mode</th><th>Description</th><th width="220">Flag</th></tr></thead><tbody><tr><td>Thorough (Default)</td><td>Include package dependencies, code coverage, all test classes during full package deployments. This is the recommended mode for comprehensive validation.</td><td><code>--mode=thorough</code></td></tr><tr><td>Individual</td><td>Ignore packages installed in scratch org, identify list of changed packages from PR/Merge Request, and validate each of the changed packages (respecting any dependencies) using thorough validation rules.</td><td><code>--mode=individual</code></td></tr></tbody></table>

### Release Config Filtering

Both validation modes support filtering packages using a release configuration file through the `--releaseconfig` flag. When provided, only packages defined in the release config that have changes will be validated. This is useful for:

* Large monorepos with multiple domains
* Focusing validation on specific package groups
* Reducing validation time by limiting scope

```bash
# Validate with release config filtering
sfp validate org --targetorg myorg --mode thorough --releaseconfig config/release.yml
```

### Evolution of Validation Modes

#### Why Fast Feedback Was Deprecated

Fast Feedback mode was initially introduced to provide quicker validation by:

* Installing only changed components instead of full packages
* Running selective tests based on impact analysis
* Skipping coverage calculations
* Skipping packages with only descriptor changes

However, this mode was **deprecated and removed** because:

1. **Complexity vs. Value**: The mode introduced significant complexity in determining what to test versus what to synchronize, while the time savings were inconsistent.
2. **Improved Alternative Approach**: The validation logic was enhanced to automatically differentiate between:

   * **Packages to synchronize**: Already validated packages from upstream changes (deployed but not tested)
   * **Packages to validate**: Packages with changes introduced by the current PR (deployed and tested)

   This automatic differentiation provides the speed benefits of fast feedback without requiring a separate mode.
3. **Better Options Available**:
   * Use `--ref` and `--baseRef` flags to specify exact comparison points
   * Use `--releaseconfig` to limit validation scope
   * Use `--skipTesting` when tests aren't needed
   * Use `individual` mode for isolated package validation

#### Currently Deprecated Modes

* **Fast Feedback** (`--mode=fastfeedback`) - Removed in favor of automatic synchronization logic
* **Fast Feedback Release Config** (`--mode=ff-release-config`) - Use `--releaseconfig` with standard modes instead
* **Thorough Release Config** (`--mode=thorough-release-config`) - Use `--mode=thorough --releaseconfig` instead

> **Note**: The current validation intelligently handles synchronized vs. validated packages automatically when you provide `--ref` and `--baseRef` flags, achieving faster feedback without a separate mode.

### Sequence of Activities

The following steps are orchestrated by the **validate** command:

#### Initial Setup

**When using pools:**

* Fetch a scratch org from the provided pools in a sequential manner
* Authenticate to the scratch org using the [auth URL](https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_auth_sfdxurl.htm) fetched from the [Scratch Org Info Object](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_scratchorginfo.htm)

**When using a provided org:**

* Authenticate to the provided target org

#### Package Processing

1. **Identify packages to validate:**
   * Build packages that are changed by comparing the tags in your repo against the packages installed in the target
   * If `--releaseconfig` is provided, filter packages based on the release configuration
2. **For each package to validate:**

   **Thorough Mode (Default):**

   * Deploy all the built packages as source packages / data packages (unlocked packages are installed as source packages)
   * Trigger Apex Tests if there are any apex tests in the package
   * Validate test coverage of the package depending on the type:
     * Source packages: Each class needs to have 75% or more coverage
     * Unlocked packages: Package as a whole needs to have 75% or more coverage

   **Individual Mode:**

   * Ignore packages that are installed in the scratch org (eliminates the requirement of using a pooled org)
   * Compute changed packages by observing the diff of Pull/Merge Request
   * Validate each of the changed packages individually
   * Install any dependencies required for each package
   * Apply thorough validation rules (deployment, testing, coverage)

### Additional Options

#### Test Execution

By default, all apex tests are triggered in parallel with automated retry. Tests that fail due to SOQL locks or other transient issues are automatically retried synchronously. You can override this behavior:

* `--disableparalleltesting`: Forces all tests to run synchronously
* `--skipTesting`: Skip test execution entirely (use with caution)

#### Coverage Requirements

* Default coverage threshold: 75%
* Configure custom threshold: `--coveragepercent <value>`
* Coverage is validated per class for source packages and per package for unlocked packages

### Combined Deploy + Test Mode (`--deploywithtests`)

By default, validate runs deploy and apex tests as two separate phases — the package metadata is deployed first, then a follow-up `RunSpecifiedTests` job triggers the package's apex tests and a third query reads the coverage. The `--deploywithtests` flag collapses this into a single Metadata API deploy that embeds the package's apex tests using `RunSpecifiedTests` with `rollbackOnError=false`. Coverage is then read directly from the deploy response.

```bash
# Combined deploy + test mode against a pool
sfp validate pool -p review -v devhub --deploywithtests

# Combined deploy + test mode against a target org
sfp validate org -o ci -v devhub --deploywithtests
```

**When combined mode is automatically disengaged**

For correctness, `sfp` falls back to the classic deploy → test flow for the packages below. The artifact header logs the reason (`Deploy With Tests: skipped — <reason>`) so you can see what ran for each package.

| Package situation                                                   | Reason for fallback                                                                                                                                                                                                                                                                                                                                                                      |
| ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Sync-only package** (not impacted by the branch under validation) | Sync-only packages are deployed without running tests in the classic flow; combined mode would force `RunSpecifiedTests` to fire for unrelated packages.                                                                                                                                                                                                                                 |
| **Pure unlocked** (Unlocked AND not org-dependent)                  | The Metadata API deploy response only carries coverage entries for classes touched by tests. The classic `ApexCodeCoverageAggregate` query is needed to get the full denominator across all package classes. `sfp` probes the DevHub once for `Package2.IsOrgDependent` to decide; if the hub is unavailable or the query fails, the package is conservatively treated as pure unlocked. |
| **Diff package with no impacted test classes**                      | Mirrors the classic `getTestOptionsForDiffPackage` behaviour — running every org-local test for an unimpacted change set is wasteful, so the package is skipped with a warning.                                                                                                                                                                                                          |
| **Non-optimized source packages with `--deploywithtests` on**       | Falls back to `RunLocalTests` (rather than `RunSpecifiedTests`) inside the same combined deploy, mirroring classic non-optimized validate semantics.                                                                                                                                                                                                                                     |

**Other guardrails**

* Per-package `skipTesting` and `skipCoverageValidation` descriptors are honored
* `--coveragepercent` is clamped to ≥ 75 (matches the classic flow)
* Org-dependent unlocked, source, and diff packages (with impacted tests) keep combined mode enabled

{% hint style="info" %}
**When to use it**: Turn on `--deploywithtests` when you want faster validate cycles and your pipeline is heavy on source/diff packages or org-dependent unlocked packages. Pure unlocked packages will continue to use the classic flow under the hood — no change in behaviour for them.
{% endhint %}

{% hint style="info" %}
**Best Practice**: Use "thorough" mode for comprehensive validation before merging to ensure all packages are properly tested and deployable. For faster feedback during development, consider using "individual" mode or filtering with release configs.
{% endhint %}

{% hint style="warning" %}
Skipping tests with `--skipTesting` bypasses critical quality checks. Only use this option in development environments or when you're certain the changes don't require test validation.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flxbl.io/flxbl/sfp/validating-a-change/different-types-of-validation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
