Testing Data Sources
Testing Data Sources Overview
Data sources read existing infrastructure. Test that they correctly query, filter, and return data.
Basic Data Source Test
func TestAccCacheDataSource_basic(t *testing.T) {
rName := acctest.RandomWithPrefix("tf-acc-test")
dataSourceName := "data.cachecloud_cache.test"
resourceName := "cachecloud_cache.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccCacheDataSourceConfig_basic(rName),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify data source matches resource
resource.TestCheckResourceAttrPair(dataSourceName, "id", resourceName, "id"),
resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName, "engine", resourceName, "engine"),
resource.TestCheckResourceAttrPair(dataSourceName, "node_type", resourceName, "node_type"),
// Verify computed attributes
resource.TestCheckResourceAttrSet(dataSourceName, "endpoint"),
resource.TestCheckResourceAttrSet(dataSourceName, "status"),
),
},
},
})
}
func testAccCacheDataSourceConfig_basic(rName string) string {
return fmt.Sprintf(`
resource "cachecloud_cache" "test" {
name = %[1]q
engine = "redis"
node_type = "cache.t3.micro"
num_nodes = 1
}
data "cachecloud_cache" "test" {
id = cachecloud_cache.test.id
}
`, rName)
}
Testing Filters
Filter by Name
func TestAccCacheDataSource_filterByName(t *testing.T) {
rName := acctest.RandomWithPrefix("tf-acc-test")
dataSourceName := "data.cachecloud_cache.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccCacheDataSourceConfig_name(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "name", rName),
resource.TestCheckResourceAttrSet(dataSourceName, "id"),
),
},
},
})
}
func testAccCacheDataSourceConfig_name(rName string) string {
return fmt.Sprintf(`
resource "cachecloud_cache" "test" {
name = %[1]q
engine = "redis"
node_type = "cache.t3.micro"
num_nodes = 1
}
data "cachecloud_cache" "test" {
name = cachecloud_cache.test.name
}
`, rName)
}
Filter by Tags
func TestAccCacheDataSource_filterByTags(t *testing.T) {
rName := acctest.RandomWithPrefix("tf-acc-test")
dataSourceName := "data.cachecloud_cache.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccCacheDataSourceConfig_tags(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "tags.%", "2"),
resource.TestCheckResourceAttr(dataSourceName, "tags.Environment", "test"),
),
},
},
})
}
Testing List Data Sources
List All
func TestAccCachesDataSource_all(t *testing.T) {
dataSourceName := "data.cachecloud_caches.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccCachesDataSourceConfig_all(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(dataSourceName, "caches.#"),
resource.TestCheckResourceAttrSet(dataSourceName, "caches.0.id"),
resource.TestCheckResourceAttrSet(dataSourceName, "caches.0.name"),
),
},
},
})
}
func testAccCachesDataSourceConfig_all() string {
return `
data "cachecloud_caches" "test" {}
`
}
List with Filter
func TestAccCachesDataSource_filter(t *testing.T) {
rName := acctest.RandomWithPrefix("tf-acc-test")
dataSourceName := "data.cachecloud_caches.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccCachesDataSourceConfig_filter(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "filter.#", "1"),
resource.TestCheckResourceAttr(dataSourceName, "filter.0.name", "engine"),
resource.TestCheckResourceAttr(dataSourceName, "filter.0.values.#", "1"),
resource.TestCheckResourceAttr(dataSourceName, "filter.0.values.0", "redis"),
// Verify results contain our cache
resource.TestCheckResourceAttrSet(dataSourceName, "caches.#"),
),
},
},
})
}
func testAccCachesDataSourceConfig_filter(rName string) string {
return fmt.Sprintf(`
resource "cachecloud_cache" "test" {
name = %[1]q
engine = "redis"
node_type = "cache.t3.micro"
num_nodes = 1
}
data "cachecloud_caches" "test" {
filter {
name = "engine"
values = ["redis"]
}
depends_on = [cachecloud_cache.test]
}
`, rName)
}
Testing Not Found
func TestAccCacheDataSource_notFound(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccCacheDataSourceConfig_notFound(),
ExpectError: regexp.MustCompile(`cache with ID .+ not found`),
},
},
})
}
func testAccCacheDataSourceConfig_notFound() string {
return `
data "cachecloud_cache" "test" {
id = "non-existent-id"
}
`
}
Testing Computed Attributes
func TestAccCacheDataSource_computedAttributes(t *testing.T) {
rName := acctest.RandomWithPrefix("tf-acc-test")
dataSourceName := "data.cachecloud_cache.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccCacheDataSourceConfig_basic(rName),
Check: resource.ComposeTestCheckFunc(
// All computed attributes should be set
resource.TestCheckResourceAttrSet(dataSourceName, "id"),
resource.TestCheckResourceAttrSet(dataSourceName, "endpoint"),
resource.TestCheckResourceAttrSet(dataSourceName, "status"),
resource.TestCheckResourceAttrSet(dataSourceName, "created_at"),
resource.TestCheckResourceAttrSet(dataSourceName, "updated_at"),
// Verify format
resource.TestMatchResourceAttr(dataSourceName, "endpoint",
regexp.MustCompile(`^[a-z0-9\-]+\.cache\.example\.com:\d+$`)),
),
},
},
})
}
Best Practices
1. Test with Resource Dependency
// ✅ Good: Create resource first
Config: `
resource "cachecloud_cache" "test" { ... }
data "cachecloud_cache" "test" {
id = cachecloud_cache.test.id
}
`
// ❌ Bad: Data source without resource
Config: `
data "cachecloud_cache" "test" {
id = "hardcoded-id"
}
`
2. Use TestCheckResourceAttrPair
// ✅ Good: Compare with resource
resource.TestCheckResourceAttrPair(
dataSourceName, "name",
resourceName, "name",
)
// ❌ Bad: Hardcode expected value
resource.TestCheckResourceAttr(dataSourceName, "name", "test")
3. Test Filters
// ✅ Good: Test filter functionality
data "cachecloud_caches" "test" {
filter {
name = "engine"
values = ["redis"]
}
}
Key Takeaways
- ✅ Test data sources with existing resources
- ✅ Verify all computed attributes
- ✅ Test filters and queries
- ✅ Use TestCheckResourceAttrPair for comparisons
- ✅ Test not found scenarios
- ✅ Test list data sources
- ✅ Verify data matches resource state
- ✅ Test multiple filter combinations
What’s Next?
Learn how to mock API clients for isolated unit testing.
Next: Mocking & Test Doubles →
Previous: ← Testing Resources
Last updated: July 3, 2026