# Testing

Complete guide for running tests in NCN Network v2.

***

## Quick Start

```bash
# Run all tests
cargo test --all

# Run tests with output
cargo test --all -- --nocapture

# Run specific package tests
cargo test -p gateway_node
```

***

## Test Categories

### Unit Tests

Located alongside source code in `src/` directories:

```bash
# Run all unit tests
cargo test --lib --all

# Run specific module tests
cargo test -p gateway_node payment::tests
```

### Integration Tests

Located in `tests/` directories:

```bash
# Run integration tests
cargo test --test '*'

# Run specific integration test
cargo test --test integration_test
```

### Contract Tests

Located in `contracts/test/`:

```bash
cd contracts

# Run all contract tests
forge test -vvv

# Run specific test
forge test --match-test testInitiateInferenceRequest -vvv

# With gas report
forge test --gas-report
```

***

## Running Tests

### All Tests

```bash
# Standard run
cargo test --all

# With verbose output
cargo test --all -- --nocapture

# With logging enabled
RUST_LOG=debug cargo test --all -- --nocapture
```

### By Package

```bash
# Common Types
cargo test -p common_types

# Gateway Node
cargo test -p gateway_node

# Compute Node
cargo test -p compute_node

# P2P Registry
cargo test -p p2p_registry_node

# Test Client
cargo test -p test_client
```

### By Test Name

```bash
# Tests containing "payment"
cargo test payment

# Tests containing "signature"
cargo test signature

# Exact test name
cargo test test_payment_tree_calculation
```

### Ignored Tests

```bash
# Run ignored tests only
cargo test --all -- --ignored

# Run all including ignored
cargo test --all -- --include-ignored
```

***

## Test Configuration

### Environment Variables

```bash
# Enable test logging
export RUST_LOG=debug
export RUST_BACKTRACE=1

# Disable parallelism (for debugging)
export RUST_TEST_THREADS=1

# Run tests
cargo test --all
```

### Test Filters

```bash
# Run tests matching pattern
cargo test payment

# Exclude tests matching pattern
cargo test -- --skip slow_test

# Run only tests in specific module
cargo test gateway_node::payment::
```

***

## Smart Contract Tests

### Foundry Tests

```bash
cd contracts

# Run all tests
forge test

# Verbose output
forge test -vvv

# Very verbose (shows traces)
forge test -vvvv

# Gas report
forge test --gas-report
```

### Specific Contract Tests

```bash
# InferencePayment tests
forge test --match-contract InferencePaymentTest

# Specific test function
forge test --match-test testInitiateInferenceRequest

# With fork
forge test --fork-url $RPC_URL
```

### Test Coverage

```bash
forge coverage

# Output to file
forge coverage --report lcov
```

***

## Integration Testing

### End-to-End Tests

```bash
# Start services first (see running-locally.md)

# Run E2E test script
./scripts/run_e2e_tests.sh

# Or manual E2E test
cargo run --bin test_client
```

### Test with Docker

```bash
# Start test environment
docker-compose -f docker-compose.test.yml up -d

# Run tests against Docker services
TEST_GATEWAY_URL=http://localhost:8080 cargo test --test integration

# Cleanup
docker-compose -f docker-compose.test.yml down
```

***

## Test Writing Guidelines

### Unit Test Example

```rust
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_payment_tree_calculation() {
        let base_price = 1_000_000_000_000_000_000u128;
        let tree = calculate_payment_tree(base_price, 0.10, 0.05, 0.05);
        
        assert_eq!(tree.compute_price_wei, "800000000000000000");
        assert_eq!(tree.gateway_gas_wei, "100000000000000000");
    }

    #[test]
    fn test_signature_verification() {
        let message = "test message";
        let private_key = "0x...";
        
        let signature = sign_message(private_key, message).unwrap();
        let valid = verify_signature(message, &signature, expected_address).unwrap();
        
        assert!(valid);
    }

    #[tokio::test]
    async fn test_async_operation() {
        let result = async_function().await;
        assert!(result.is_ok());
    }
}
```

### Integration Test Example

```rust
// tests/integration_test.rs
use common_types::*;

#[tokio::test]
async fn test_full_inference_flow() {
    // Setup
    let gateway = start_test_gateway().await;
    let compute = start_test_compute().await;
    
    // Test
    let request = InferenceRequest {
        request_id: "test-123".to_string(),
        model_uuid: "test_model".to_string(),
        input_data: "{}".to_string(),
        ..Default::default()
    };
    
    let response = gateway.submit_task(request).await.unwrap();
    
    // Assert
    assert_eq!(response.status, "completed");
    
    // Cleanup
    gateway.stop().await;
    compute.stop().await;
}
```

### Contract Test Example

```solidity
// contracts/test/InferencePayment.t.sol
contract InferencePaymentTest is Test {
    InferencePayment payment;
    NCNToken token;
    
    function setUp() public {
        token = new NCNToken();
        payment = new InferencePayment(address(token), treasury, 3);
    }
    
    function testInitiateInferenceRequest() public {
        // Setup
        bytes32 requestId = keccak256("test");
        uint256 amount = 1 ether;
        
        token.approve(address(payment), amount);
        
        // Test
        payment.initiateInferenceRequest(
            requestId,
            gateway,
            computeNode,
            computePrice,
            gatewayGas,
            validatorReward,
            treasuryFee,
            block.timestamp + 1 hours,
            signatures
        );
        
        // Assert
        assertTrue(payment.requestExists(requestId));
    }
}
```

***

## Test Utilities

### Test Helpers

```rust
// Common test utilities
#[cfg(test)]
mod test_utils {
    pub fn create_test_request() -> InferenceRequest {
        InferenceRequest {
            request_id: uuid::Uuid::new_v4().to_string(),
            model_uuid: "test_model".to_string(),
            input_data: "{}".to_string(),
            ..Default::default()
        }
    }
    
    pub fn generate_test_wallet() -> (String, String) {
        let wallet = LocalWallet::new(&mut rand::thread_rng());
        (format!("{:?}", wallet.address()), format!("{:x}", wallet))
    }
}
```

### Mock Services

```rust
#[cfg(test)]
pub struct MockGateway {
    responses: HashMap<String, InferenceResponse>,
}

impl MockGateway {
    pub fn new() -> Self {
        Self { responses: HashMap::new() }
    }
    
    pub fn with_response(mut self, request_id: &str, response: InferenceResponse) -> Self {
        self.responses.insert(request_id.to_string(), response);
        self
    }
}
```

***

## CI/CD Testing

### GitHub Actions Example

```yaml
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
        
      - name: Install protoc
        run: sudo apt-get install -y protobuf-compiler
        
      - name: Run tests
        run: cargo test --all --verbose
        
      - name: Run clippy
        run: cargo clippy --all -- -D warnings
```

***

## Test Coverage

### Generate Coverage Report

```bash
# Install cargo-tarpaulin
cargo install cargo-tarpaulin

# Generate coverage
cargo tarpaulin --all --out Html

# View report
open tarpaulin-report.html
```

### Coverage Targets

| Component       | Target Coverage |
| --------------- | --------------- |
| Common Types    | 90%             |
| Gateway Node    | 80%             |
| Compute Node    | 75%             |
| P2P Registry    | 80%             |
| Smart Contracts | 95%             |

***

## Debugging Failed Tests

### Enable Backtrace

```bash
RUST_BACKTRACE=1 cargo test test_name
```

### Run Single Test Verbose

```bash
cargo test test_name -- --nocapture
```

### Run with Logging

```bash
RUST_LOG=trace cargo test test_name -- --nocapture
```

### Debug in IDE

Configure VS Code launch.json:

```json
{
  "type": "lldb",
  "request": "launch",
  "name": "Debug test",
  "cargo": {
    "args": ["test", "--no-run", "-p", "gateway_node"],
    "filter": {
      "kind": "test"
    }
  }
}
```

***

## Next Steps

* [Debugging](/nc/neurochainai-guides/development/debugging.md) - Debug issues
* [Running Locally](/nc/neurochainai-guides/development/running-locally.md) - Local development
* [Contributing](/nc/neurochainai-guides/contributing/contributing.md) - Contribute to tests


---

# 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.neurochain.ai/nc/neurochainai-guides/development/testing.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.
