Skip to content

Commit 4ed7aad

Browse files
jsoucheironclaude
andcommitted
Add test files for all resource types missing tests
Added tests for 10 resource types that had model implementations but no corresponding test files: - test_autoscaling_auto_scaling_group.py - test_cloudwatch_alarm.py - test_dynamodb_table.py - test_elbv2_listener.py - test_elbv2_target_group.py - test_iam_instance_profile.py - test_route53_record_set.py - test_sns_subscription.py - test_sns_topic.py - test_sqs_queue.py Each test file covers: - Basic resource instantiation - Property validation - Required field validation - Nested object handling - Common use cases for the resource type Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 2ef40ef commit 4ed7aad

10 files changed

+1421
-0
lines changed
Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
import pytest
2+
from pydantic import ValidationError
3+
4+
from pycfmodel.model.resources.autoscaling_auto_scaling_group import AutoScalingAutoScalingGroup
5+
6+
7+
@pytest.fixture()
8+
def valid_autoscaling_group():
9+
return AutoScalingAutoScalingGroup(
10+
**{
11+
"Type": "AWS::AutoScaling::AutoScalingGroup",
12+
"Properties": {
13+
"AutoScalingGroupName": "my-asg",
14+
"MinSize": "1",
15+
"MaxSize": "10",
16+
"DesiredCapacity": "2",
17+
"LaunchTemplate": {
18+
"LaunchTemplateId": "lt-1234567890abcdef0",
19+
"Version": "$Latest",
20+
},
21+
"VPCZoneIdentifier": ["subnet-1234567890abcdef0", "subnet-0987654321fedcba0"],
22+
},
23+
}
24+
)
25+
26+
27+
def test_valid_autoscaling_group_resource(valid_autoscaling_group):
28+
assert valid_autoscaling_group.Properties.AutoScalingGroupName == "my-asg"
29+
assert valid_autoscaling_group.Properties.MinSize == "1"
30+
assert valid_autoscaling_group.Properties.MaxSize == "10"
31+
assert valid_autoscaling_group.Properties.DesiredCapacity == "2"
32+
33+
34+
def test_autoscaling_group_with_launch_configuration():
35+
asg = AutoScalingAutoScalingGroup(
36+
**{
37+
"Type": "AWS::AutoScaling::AutoScalingGroup",
38+
"Properties": {
39+
"MinSize": "1",
40+
"MaxSize": "5",
41+
"LaunchConfigurationName": "my-launch-config",
42+
"AvailabilityZones": ["us-east-1a", "us-east-1b"],
43+
},
44+
}
45+
)
46+
assert asg.Properties.LaunchConfigurationName == "my-launch-config"
47+
assert len(asg.Properties.AvailabilityZones) == 2
48+
49+
50+
def test_autoscaling_group_with_mixed_instances_policy():
51+
asg = AutoScalingAutoScalingGroup(
52+
**{
53+
"Type": "AWS::AutoScaling::AutoScalingGroup",
54+
"Properties": {
55+
"MinSize": "1",
56+
"MaxSize": "10",
57+
"VPCZoneIdentifier": ["subnet-123"],
58+
"MixedInstancesPolicy": {
59+
"LaunchTemplate": {
60+
"LaunchTemplateSpecification": {
61+
"LaunchTemplateId": "lt-123",
62+
"Version": "$Latest",
63+
},
64+
"Overrides": [
65+
{"InstanceType": "t3.micro"},
66+
{"InstanceType": "t3.small"},
67+
{"InstanceType": "t3.medium"},
68+
],
69+
},
70+
"InstancesDistribution": {
71+
"OnDemandBaseCapacity": 1,
72+
"OnDemandPercentageAboveBaseCapacity": 25,
73+
"SpotAllocationStrategy": "capacity-optimized",
74+
},
75+
},
76+
},
77+
}
78+
)
79+
assert len(asg.Properties.MixedInstancesPolicy.LaunchTemplate.Overrides) == 3
80+
assert asg.Properties.MixedInstancesPolicy.InstancesDistribution.OnDemandBaseCapacity == 1
81+
82+
83+
def test_autoscaling_group_with_target_groups():
84+
asg = AutoScalingAutoScalingGroup(
85+
**{
86+
"Type": "AWS::AutoScaling::AutoScalingGroup",
87+
"Properties": {
88+
"MinSize": "1",
89+
"MaxSize": "5",
90+
"LaunchTemplate": {
91+
"LaunchTemplateId": "lt-123",
92+
"Version": "$Latest",
93+
},
94+
"VPCZoneIdentifier": ["subnet-123"],
95+
"TargetGroupARNs": [
96+
"arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/my-tg/1234567890123456"
97+
],
98+
},
99+
}
100+
)
101+
assert len(asg.Properties.TargetGroupARNs) == 1
102+
103+
104+
def test_autoscaling_group_with_health_check():
105+
asg = AutoScalingAutoScalingGroup(
106+
**{
107+
"Type": "AWS::AutoScaling::AutoScalingGroup",
108+
"Properties": {
109+
"MinSize": "1",
110+
"MaxSize": "5",
111+
"LaunchTemplate": {
112+
"LaunchTemplateId": "lt-123",
113+
"Version": "$Latest",
114+
},
115+
"VPCZoneIdentifier": ["subnet-123"],
116+
"HealthCheckType": "ELB",
117+
"HealthCheckGracePeriod": 300,
118+
},
119+
}
120+
)
121+
assert asg.Properties.HealthCheckType == "ELB"
122+
assert asg.Properties.HealthCheckGracePeriod == 300
123+
124+
125+
def test_autoscaling_group_with_lifecycle_hooks():
126+
asg = AutoScalingAutoScalingGroup(
127+
**{
128+
"Type": "AWS::AutoScaling::AutoScalingGroup",
129+
"Properties": {
130+
"MinSize": "1",
131+
"MaxSize": "5",
132+
"LaunchTemplate": {
133+
"LaunchTemplateId": "lt-123",
134+
"Version": "$Latest",
135+
},
136+
"VPCZoneIdentifier": ["subnet-123"],
137+
"LifecycleHookSpecificationList": [
138+
{
139+
"LifecycleHookName": "launch-hook",
140+
"LifecycleTransition": "autoscaling:EC2_INSTANCE_LAUNCHING",
141+
"DefaultResult": "CONTINUE",
142+
"HeartbeatTimeout": 300,
143+
}
144+
],
145+
},
146+
}
147+
)
148+
assert len(asg.Properties.LifecycleHookSpecificationList) == 1
149+
assert asg.Properties.LifecycleHookSpecificationList[0].LifecycleHookName == "launch-hook"
150+
151+
152+
def test_autoscaling_group_with_notification():
153+
asg = AutoScalingAutoScalingGroup(
154+
**{
155+
"Type": "AWS::AutoScaling::AutoScalingGroup",
156+
"Properties": {
157+
"MinSize": "1",
158+
"MaxSize": "5",
159+
"LaunchTemplate": {
160+
"LaunchTemplateId": "lt-123",
161+
"Version": "$Latest",
162+
},
163+
"VPCZoneIdentifier": ["subnet-123"],
164+
"NotificationConfiguration": {
165+
"TopicARN": "arn:aws:sns:us-east-1:123456789012:my-topic",
166+
"NotificationTypes": [
167+
"autoscaling:EC2_INSTANCE_LAUNCH",
168+
"autoscaling:EC2_INSTANCE_TERMINATE",
169+
],
170+
},
171+
},
172+
}
173+
)
174+
assert asg.Properties.NotificationConfiguration.TopicARN == "arn:aws:sns:us-east-1:123456789012:my-topic"
175+
176+
177+
def test_autoscaling_group_with_tags():
178+
asg = AutoScalingAutoScalingGroup(
179+
**{
180+
"Type": "AWS::AutoScaling::AutoScalingGroup",
181+
"Properties": {
182+
"MinSize": "1",
183+
"MaxSize": "5",
184+
"LaunchTemplate": {
185+
"LaunchTemplateId": "lt-123",
186+
"Version": "$Latest",
187+
},
188+
"VPCZoneIdentifier": ["subnet-123"],
189+
"Tags": [
190+
{"Key": "Environment", "Value": "production", "PropagateAtLaunch": True},
191+
{"Key": "Application", "Value": "web", "PropagateAtLaunch": True},
192+
],
193+
},
194+
}
195+
)
196+
assert len(asg.Properties.Tags) == 2
197+
assert asg.Properties.Tags[0].PropagateAtLaunch is True
198+
199+
200+
def test_autoscaling_group_with_instance_maintenance_policy():
201+
asg = AutoScalingAutoScalingGroup(
202+
**{
203+
"Type": "AWS::AutoScaling::AutoScalingGroup",
204+
"Properties": {
205+
"MinSize": "1",
206+
"MaxSize": "5",
207+
"LaunchTemplate": {
208+
"LaunchTemplateId": "lt-123",
209+
"Version": "$Latest",
210+
},
211+
"VPCZoneIdentifier": ["subnet-123"],
212+
"InstanceMaintenancePolicy": {
213+
"MinHealthyPercentage": 90,
214+
"MaxHealthyPercentage": 120,
215+
},
216+
},
217+
}
218+
)
219+
assert asg.Properties.InstanceMaintenancePolicy.MinHealthyPercentage == 90
220+
221+
222+
def test_autoscaling_group_requires_min_size():
223+
with pytest.raises(ValidationError):
224+
AutoScalingAutoScalingGroup(
225+
**{
226+
"Type": "AWS::AutoScaling::AutoScalingGroup",
227+
"Properties": {
228+
"MaxSize": "5",
229+
"LaunchTemplate": {
230+
"LaunchTemplateId": "lt-123",
231+
"Version": "$Latest",
232+
},
233+
},
234+
}
235+
)
236+
237+
238+
def test_autoscaling_group_requires_max_size():
239+
with pytest.raises(ValidationError):
240+
AutoScalingAutoScalingGroup(
241+
**{
242+
"Type": "AWS::AutoScaling::AutoScalingGroup",
243+
"Properties": {
244+
"MinSize": "1",
245+
"LaunchTemplate": {
246+
"LaunchTemplateId": "lt-123",
247+
"Version": "$Latest",
248+
},
249+
},
250+
}
251+
)
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import pytest
2+
from pydantic import ValidationError
3+
4+
from pycfmodel.model.resources.cloudwatch_alarm import CloudWatchAlarm
5+
6+
7+
@pytest.fixture()
8+
def valid_cloudwatch_alarm():
9+
return CloudWatchAlarm(
10+
**{
11+
"Type": "AWS::CloudWatch::Alarm",
12+
"Properties": {
13+
"AlarmName": "high-cpu-alarm",
14+
"AlarmDescription": "Alarm when CPU exceeds 80%",
15+
"MetricName": "CPUUtilization",
16+
"Namespace": "AWS/EC2",
17+
"Statistic": "Average",
18+
"Period": 300,
19+
"EvaluationPeriods": 2,
20+
"Threshold": 80,
21+
"ComparisonOperator": "GreaterThanThreshold",
22+
},
23+
}
24+
)
25+
26+
27+
def test_valid_cloudwatch_alarm_resource(valid_cloudwatch_alarm):
28+
assert valid_cloudwatch_alarm.Properties.AlarmName == "high-cpu-alarm"
29+
assert valid_cloudwatch_alarm.Properties.MetricName == "CPUUtilization"
30+
assert valid_cloudwatch_alarm.Properties.Namespace == "AWS/EC2"
31+
assert valid_cloudwatch_alarm.Properties.Threshold == 80
32+
assert valid_cloudwatch_alarm.Properties.ComparisonOperator == "GreaterThanThreshold"
33+
34+
35+
def test_cloudwatch_alarm_with_dimensions():
36+
alarm = CloudWatchAlarm(
37+
**{
38+
"Type": "AWS::CloudWatch::Alarm",
39+
"Properties": {
40+
"AlarmName": "instance-cpu-alarm",
41+
"MetricName": "CPUUtilization",
42+
"Namespace": "AWS/EC2",
43+
"EvaluationPeriods": 1,
44+
"ComparisonOperator": "GreaterThanThreshold",
45+
"Dimensions": [{"Name": "InstanceId", "Value": "i-1234567890abcdef0"}],
46+
"Period": 60,
47+
"Statistic": "Average",
48+
"Threshold": 90,
49+
},
50+
}
51+
)
52+
assert len(alarm.Properties.Dimensions) == 1
53+
assert alarm.Properties.Dimensions[0].Name == "InstanceId"
54+
55+
56+
def test_cloudwatch_alarm_with_actions():
57+
alarm = CloudWatchAlarm(
58+
**{
59+
"Type": "AWS::CloudWatch::Alarm",
60+
"Properties": {
61+
"AlarmName": "cpu-alarm",
62+
"MetricName": "CPUUtilization",
63+
"Namespace": "AWS/EC2",
64+
"EvaluationPeriods": 1,
65+
"ComparisonOperator": "GreaterThanThreshold",
66+
"AlarmActions": ["arn:aws:sns:us-east-1:123456789012:my-topic"],
67+
"OKActions": ["arn:aws:sns:us-east-1:123456789012:my-topic"],
68+
"InsufficientDataActions": ["arn:aws:sns:us-east-1:123456789012:my-topic"],
69+
},
70+
}
71+
)
72+
assert len(alarm.Properties.AlarmActions) == 1
73+
assert len(alarm.Properties.OKActions) == 1
74+
75+
76+
def test_cloudwatch_alarm_with_metric_math():
77+
alarm = CloudWatchAlarm(
78+
**{
79+
"Type": "AWS::CloudWatch::Alarm",
80+
"Properties": {
81+
"AlarmName": "metric-math-alarm",
82+
"EvaluationPeriods": 1,
83+
"ComparisonOperator": "GreaterThanThreshold",
84+
"Threshold": 100,
85+
"Metrics": [
86+
{
87+
"Id": "e1",
88+
"Expression": "m1 + m2",
89+
"Label": "Sum of metrics",
90+
"ReturnData": True,
91+
},
92+
{
93+
"Id": "m1",
94+
"MetricStat": {
95+
"Metric": {"MetricName": "Metric1", "Namespace": "Custom"},
96+
"Period": 60,
97+
"Stat": "Sum",
98+
},
99+
"ReturnData": False,
100+
},
101+
],
102+
},
103+
}
104+
)
105+
assert len(alarm.Properties.Metrics) == 2
106+
assert alarm.Properties.Metrics[0].Expression == "m1 + m2"
107+
108+
109+
def test_cloudwatch_alarm_requires_comparison_operator():
110+
with pytest.raises(ValidationError):
111+
CloudWatchAlarm(
112+
**{
113+
"Type": "AWS::CloudWatch::Alarm",
114+
"Properties": {
115+
"AlarmName": "my-alarm",
116+
"EvaluationPeriods": 1,
117+
},
118+
}
119+
)
120+
121+
122+
def test_cloudwatch_alarm_requires_evaluation_periods():
123+
with pytest.raises(ValidationError):
124+
CloudWatchAlarm(
125+
**{
126+
"Type": "AWS::CloudWatch::Alarm",
127+
"Properties": {
128+
"AlarmName": "my-alarm",
129+
"ComparisonOperator": "GreaterThanThreshold",
130+
},
131+
}
132+
)

0 commit comments

Comments
 (0)