aplos-nca-saas-sdk 0.0.14__tar.gz → 0.0.16__tar.gz

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 (71) hide show
  1. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/PKG-INFO +1 -1
  2. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/pyproject.toml +1 -1
  3. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/configs/app_settings_config.py +2 -0
  4. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/configs/file_upload_config.py +4 -1
  5. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/configs/login_config.py +3 -0
  6. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/configs/nca_execution_config.py +6 -2
  7. aplos_nca_saas_sdk-0.0.16/src/aplos_nca_saas_sdk/integration_testing/configs/nca_validation_config.py +95 -0
  8. aplos_nca_saas_sdk-0.0.14/src/aplos_nca_saas_sdk/integration_testing/main.py → aplos_nca_saas_sdk-0.0.16/src/aplos_nca_saas_sdk/integration_testing/example_main.py +15 -7
  9. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/integration_test_configurations.py +6 -0
  10. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/integration_test_suite.py +9 -9
  11. aplos_nca_saas_sdk-0.0.16/src/aplos_nca_saas_sdk/integration_testing/readme.md +205 -0
  12. aplos_nca_saas_sdk-0.0.16/src/aplos_nca_saas_sdk/integration_testing/tests/nca_analysis_validation_test.py +62 -0
  13. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/nca_resources/nca_analysis.py +1 -1
  14. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/nca_resources/nca_authenticator.py +5 -0
  15. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/nca_resources/nca_endpoints.py +4 -0
  16. aplos_nca_saas_sdk-0.0.16/src/aplos_nca_saas_sdk/nca_resources/nca_validations.py +101 -0
  17. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/version.py +1 -1
  18. aplos_nca_saas_sdk-0.0.14/src/aplos_nca_saas_sdk/integration_testing/readme.md +0 -18
  19. aplos_nca_saas_sdk-0.0.14/src/aplos_nca_saas_sdk/integration_testing/tests/validation_test.py +0 -5
  20. aplos_nca_saas_sdk-0.0.14/src/aplos_nca_saas_sdk/nca_resources/nca_validations.py +0 -34
  21. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/.gitignore +0 -0
  22. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/.pypirc +0 -0
  23. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/.vscode/launch.json +0 -0
  24. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/.vscode/settings.json +0 -0
  25. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/LICENSE +0 -0
  26. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/README.md +0 -0
  27. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/devops/pypi/build.py +0 -0
  28. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/devops/pypi/readme.md +0 -0
  29. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/devops/requirements.txt +0 -0
  30. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/docs/images/API_Configuration_blur.png +0 -0
  31. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/docs/images/aplos-nca-commandline-cropped.png +0 -0
  32. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/docs/images/aplos-nca-commandline.png +0 -0
  33. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/mypy.ini +0 -0
  34. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/mypy_checks.py +0 -0
  35. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/readme.md +0 -0
  36. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/requirements.txt +0 -0
  37. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/run-checks.sh +0 -0
  38. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/__init__.py +0 -0
  39. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/configs/_config_base.py +0 -0
  40. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/configs/config_sample.json +0 -0
  41. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/files/executions/config1.json +0 -0
  42. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.csv +0 -0
  43. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.dat +0 -0
  44. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.sas7bdat +0 -0
  45. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.xls +0 -0
  46. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.xlsx +0 -0
  47. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.xpt +0 -0
  48. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/integration_test_base.py +0 -0
  49. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/integration_test_factory.py +0 -0
  50. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/integration_test_response.py +0 -0
  51. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/tests/app_configuration_test.py +0 -0
  52. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/tests/app_login_test.py +0 -0
  53. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/tests/file_upload_test.py +0 -0
  54. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/integration_testing/tests/nca_analysis_test.py +0 -0
  55. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/nca_resources/_api_base.py +0 -0
  56. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/nca_resources/aws_cognito.py +0 -0
  57. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/nca_resources/aws_s3_presigned_payload.py +0 -0
  58. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/nca_resources/aws_s3_presigned_upload.py +0 -0
  59. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/nca_resources/nca_app_configuration.py +0 -0
  60. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/nca_resources/nca_file_download.py +0 -0
  61. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/nca_resources/nca_file_upload.py +0 -0
  62. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/run_analysis_execution.py +0 -0
  63. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/sample_files/analysis_files/single_ev/config.json +0 -0
  64. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/sample_files/analysis_files/single_ev/input.csv +0 -0
  65. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/sample_files/analysis_files/single_ev/meta_data.json +0 -0
  66. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/utilities/commandline_args.py +0 -0
  67. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/utilities/environment_services.py +0 -0
  68. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/utilities/environment_vars.py +0 -0
  69. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/utilities/file_utility.py +0 -0
  70. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/src/aplos_nca_saas_sdk/utilities/http_utility.py +0 -0
  71. {aplos_nca_saas_sdk-0.0.14 → aplos_nca_saas_sdk-0.0.16}/tests/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aplos_nca_saas_sdk
3
- Version: 0.0.14
3
+ Version: 0.0.16
4
4
  Summary: Aplos NCA SaaS SDK
5
5
  Project-URL: Homepage, https://aplosanalytics.com/
6
6
  Project-URL: Documentation, https://docs.aplosanalytics.com/
@@ -26,7 +26,7 @@ keywords = [
26
26
  "Clinical Trials"
27
27
  ]
28
28
 
29
- version = "0.0.14"
29
+ version = "0.0.16"
30
30
  authors = [
31
31
  { name="Eric Wilson", email="eric.wilson@aplosanalytics.com" }
32
32
  ]
@@ -85,4 +85,6 @@ class ApplicationSettings(ConfigBase):
85
85
  def load(self, test_config: Dict[str, Any]):
86
86
  """Load the hosts from the config"""
87
87
  super().load(test_config)
88
+ if not self.enabled:
89
+ return
88
90
  self.hosts.load(test_config)
@@ -11,7 +11,7 @@ from aplos_nca_saas_sdk.integration_testing.configs.login_config import (
11
11
  LoginConfig,
12
12
  LoginConfigs,
13
13
  )
14
- from aplos_nca_saas_sdk.utilities.environment_services import EnvironmentServices
14
+
15
15
  from aplos_nca_saas_sdk.utilities.file_utility import FileUtility
16
16
 
17
17
 
@@ -71,6 +71,9 @@ class FileUploadConfigs(ConfigBase):
71
71
  """Load the file uploads from a list of dictionaries"""
72
72
 
73
73
  super().load(test_config)
74
+ if not self.enabled:
75
+ return
76
+
74
77
  test_config_login: LoginConfig | None = LoginConfigs.try_load_login(
75
78
  test_config.get("login", None)
76
79
  )
@@ -98,6 +98,9 @@ class LoginConfigs(ConfigBase):
98
98
  """Load the logins from a list of dictionaries"""
99
99
 
100
100
  super().load(test_config)
101
+ if not self.enabled:
102
+ return
103
+
101
104
  logins: List[Dict[str, str]] = test_config.get("logins", [])
102
105
  for login in logins:
103
106
  login_config = LoginConfigs.try_load_login(login)
@@ -4,16 +4,18 @@ All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
4
4
  Property of Aplos Analytics, Utah, USA
5
5
  """
6
6
 
7
- import os
8
7
  import json
8
+ import os
9
9
  from typing import Any, Dict, List
10
+
11
+ from aws_lambda_powertools import Logger
12
+
10
13
  from aplos_nca_saas_sdk.integration_testing.configs._config_base import ConfigBase
11
14
  from aplos_nca_saas_sdk.integration_testing.configs.login_config import (
12
15
  LoginConfig,
13
16
  LoginConfigs,
14
17
  )
15
18
  from aplos_nca_saas_sdk.utilities.file_utility import FileUtility
16
- from aws_lambda_powertools import Logger
17
19
 
18
20
  logger = Logger(service="NCAExecutionConfig")
19
21
 
@@ -124,6 +126,8 @@ class NCAExecutionConfigs(ConfigBase):
124
126
  """Loads the NCA Execution configs from a list of dictionaries"""
125
127
 
126
128
  super().load(test_config)
129
+ if not self.enabled:
130
+ return
127
131
 
128
132
  base_login: LoginConfig | None = LoginConfigs.try_load_login(
129
133
  test_config.get("login", None)
@@ -0,0 +1,95 @@
1
+ """
2
+ Copyright 2024-2025 Aplos Analytics
3
+ All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
4
+ Property of Aplos Analytics, Utah, USA
5
+ """
6
+
7
+ from typing import Any, Dict, List
8
+
9
+ from aws_lambda_powertools import Logger
10
+
11
+ from aplos_nca_saas_sdk.integration_testing.configs._config_base import ConfigBase
12
+ from aplos_nca_saas_sdk.integration_testing.configs.login_config import (
13
+ LoginConfig,
14
+ LoginConfigs,
15
+ )
16
+
17
+
18
+ logger = Logger(service="NCAValidationConfig")
19
+
20
+
21
+ class NCAValidationConfig(ConfigBase):
22
+ """
23
+ NCA Validation Config: Defines an NCA Validation configuration that the application tests will check against
24
+
25
+ """
26
+
27
+ def __init__(
28
+ self,
29
+ login: LoginConfig,
30
+ ):
31
+ super().__init__()
32
+
33
+ if login is None:
34
+ raise RuntimeError("login is required")
35
+ self.__login = login
36
+
37
+ @property
38
+ def login(self) -> LoginConfig:
39
+ """Login Configuration"""
40
+ return self.__login
41
+
42
+
43
+ class NCAValidationConfigs(ConfigBase):
44
+ """
45
+ NCA Validation Configs: Defines the configurations that the application NCA Engine tests will check against
46
+
47
+ """
48
+
49
+ def __init__(self):
50
+ super().__init__()
51
+ self.__list: List[NCAValidationConfig] = []
52
+
53
+ @property
54
+ def list(self) -> List[NCAValidationConfig]:
55
+ """List the nca validation configurations"""
56
+ return list(filter(lambda x: x.enabled, self.__list))
57
+
58
+ def add(
59
+ self,
60
+ *,
61
+ login: LoginConfig,
62
+ enabled: bool = True,
63
+ ):
64
+ """Add an NCA Validation Config"""
65
+ config = NCAValidationConfig(login)
66
+ config.enabled = enabled
67
+ self.__list.append(config)
68
+
69
+ def load(self, test_config: Dict[str, Any]):
70
+ """Loads the NCA Validation configs from a list of dictionaries"""
71
+
72
+ super().load(test_config)
73
+ if not self.enabled:
74
+ return
75
+
76
+ base_login: LoginConfig | None = LoginConfigs.try_load_login(
77
+ test_config.get("login", None)
78
+ )
79
+
80
+ validations: List[Dict[str, Any]] = test_config.get("validations", [])
81
+ for validation in validations:
82
+ enabled = bool(validation.get("enabled", True))
83
+ login: LoginConfig | None = None
84
+ if "login" in validation:
85
+ login = LoginConfigs.try_load_login(validation["login"])
86
+ else:
87
+ login = base_login
88
+
89
+ if not login:
90
+ raise RuntimeError("Failed to load the login configuration")
91
+
92
+ self.add(
93
+ login=login,
94
+ enabled=enabled,
95
+ )
@@ -16,19 +16,25 @@ from aplos_nca_saas_sdk.integration_testing.integration_test_configurations impo
16
16
 
17
17
 
18
18
  def main():
19
- """Run the tests"""
19
+ """This is an example on how you can run the unit tests"""
20
20
 
21
+ # Optionally use our convient Environment Services loader
22
+ # which can help during intial testings.
21
23
  evs: EnvironmentServices = EnvironmentServices()
24
+ # see if we have a local .env, .env.uat, etc configured to look up
22
25
  env_file = os.getenv("ENV_FILE")
23
26
  if env_file:
24
27
  # if we have an environment file defined, let's load it
25
28
  evs.load_environment(starting_path=__file__, file_name=env_file)
26
29
 
30
+ # this is where the work begins
27
31
  its: IntegrationTestSuite = IntegrationTestSuite()
28
32
  config: TestConfiguration = TestConfiguration()
29
33
 
30
- # normally we'd pull a test configuration file from Secrets Manager, Parameter Store, or some other secure location
31
- # here we're going to pull the sample file and then override some it's values.
34
+ # here were going to load a config file that is local, for security purpose
35
+ # you should store this in SecretsManager, Parameter Store, a secure S3 bucket etc.
36
+ # the configs typically contain sensitive information like usernames & passwords
37
+ # so be careful where you store it!
32
38
  config_file = os.path.join(
33
39
  Path(__file__).parent,
34
40
  "configs",
@@ -37,14 +43,16 @@ def main():
37
43
  # load it so we can see what it looks like
38
44
  config.load(file_path=config_file)
39
45
 
40
- # override the configuration
41
- # override_config(config)
42
-
46
+ # run the tests
43
47
  its.test(test_config=config)
44
48
 
45
49
 
46
50
  def override_config(config: TestConfiguration):
47
- """Override the configuration for the tests"""
51
+ """
52
+ Override the configuration for the tests.
53
+ This is some sample code how you can use a combination of a config file
54
+ and then override the username/password combos using environment vars.
55
+ """
48
56
  username = os.getenv("TEST_USERNAME")
49
57
  password = os.getenv("TEST_PASSWORD")
50
58
  host = os.getenv("TEST_HOST")
@@ -17,6 +17,10 @@ from aplos_nca_saas_sdk.integration_testing.configs.nca_execution_config import
17
17
  NCAExecutionConfigs,
18
18
  )
19
19
 
20
+ from aplos_nca_saas_sdk.integration_testing.configs.nca_validation_config import (
21
+ NCAValidationConfigs,
22
+ )
23
+
20
24
 
21
25
  class TestConfiguration:
22
26
  """
@@ -29,6 +33,7 @@ class TestConfiguration:
29
33
  self.logins: LoginConfigs = LoginConfigs()
30
34
  self.file_uploads: FileUploadConfigs = FileUploadConfigs()
31
35
  self.nca_executions: NCAExecutionConfigs = NCAExecutionConfigs()
36
+ self.nca_validations: NCAValidationConfigs = NCAValidationConfigs()
32
37
 
33
38
  def load(self, file_path: str):
34
39
  """
@@ -46,3 +51,4 @@ class TestConfiguration:
46
51
  self.app_config.load(config.get("application_config_test", {}))
47
52
  self.file_uploads.load(config.get("file_upload_test", {}))
48
53
  self.nca_executions.load(config.get("analysis_execution_test", {}))
54
+ self.nca_validations.load(config.get("analysis_validation_test", {}))
@@ -70,15 +70,15 @@ class IntegrationTestSuite:
70
70
  if self.fail_fast:
71
71
  # just break and let the failure routine handle it
72
72
  break
73
-
74
- test_result["end_time_utc"] = datetime.now(UTC)
75
- self.test_results.append(test_result)
76
-
77
- if test_result["success"]:
78
- logger.info(f"Test {test.name} succeeded")
79
- logger.debug(test_result)
80
- else:
81
- logger.error(test_result)
73
+ finally:
74
+ test_result["end_time_utc"] = datetime.now(UTC)
75
+ self.test_results.append(test_result)
76
+
77
+ if test_result["success"]:
78
+ logger.info(f"Test {test.name} succeeded")
79
+ logger.debug(test_result)
80
+ else:
81
+ logger.error(test_result)
82
82
  # find the failures
83
83
  failures = [test for test in self.test_results if len(test["errors"]) > 0]
84
84
  self.__print_results(start_time, failures)
@@ -0,0 +1,205 @@
1
+ # Integration Test
2
+
3
+ This module runs integration tests against a live environment. The goal is to catch anything before it's deployed.
4
+ However you can also use this as a learning tool or a base on how to use our API's.
5
+
6
+ ## Requirements
7
+ The integration tests will require the following:
8
+ - A valid user Aplos NCA User Account
9
+ - A valid subscription
10
+
11
+
12
+ ### Users
13
+ You will need valid user accounts with the appropriate permissions for the endpoints they are executing.
14
+
15
+ If you are testing permission bounderies then you should set up multiple users with different permissions.
16
+
17
+
18
+ ### Subscriptions
19
+ Your subscription will control how may executions are allowed for user or tenancy. Make sure you have enough executions. If you need
20
+ additional executions, please reach-out to your support contact.
21
+
22
+ ## Running the test
23
+ See the `example_main.py` for updated examples, but in general you follow the code below to run tests. Also, see the `configs` section below
24
+ for guidance on defining what is tested.
25
+
26
+ ```python
27
+ """
28
+ Copyright 2024-2025 Aplos Analytics
29
+ All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
30
+ Property of Aplos Analytics, Utah, USA
31
+ """
32
+
33
+ import os
34
+ from pathlib import Path
35
+ from aplos_nca_saas_sdk.utilities.environment_services import EnvironmentServices
36
+ from aplos_nca_saas_sdk.integration_testing.integration_test_suite import (
37
+ IntegrationTestSuite,
38
+ )
39
+ from aplos_nca_saas_sdk.integration_testing.integration_test_configurations import (
40
+ TestConfiguration,
41
+ )
42
+
43
+
44
+ def main():
45
+ """This is an example on how you can run the unit tests"""
46
+
47
+ # Optionally use our convient Environment Services loader
48
+ # which can help during intial testings.
49
+ evs: EnvironmentServices = EnvironmentServices()
50
+ # See if we have a local .env, .env.uat, etc configured to look up
51
+ # for local configuration settings
52
+ #
53
+ # Use local .env files when testing locally. As a best practice
54
+ # you should avoid adding these to source control or deployments.
55
+ env_file = os.getenv("ENV_FILE")
56
+ if env_file:
57
+ # if we have an environment file defined, let's load it
58
+ # this will prep our environment with local values.
59
+ evs.load_environment(starting_path=__file__, file_name=env_file)
60
+
61
+ # this is where the work begins
62
+ its: IntegrationTestSuite = IntegrationTestSuite()
63
+ config: TestConfiguration = TestConfiguration()
64
+
65
+ # here were going to load a config file that is local, for security purpose
66
+ # you should store this in SecretsManager, Parameter Store, a secure S3 bucket etc.
67
+ # the configs typically contain sensitive information like usernames & passwords
68
+ # so be careful where you store it!
69
+ config_file = os.path.join(
70
+ Path(__file__).parent,
71
+ "configs",
72
+ os.getenv("TEST_CONFIG_FILE") or "config_sample.json",
73
+ )
74
+ # load it so we can see what it looks like
75
+ config.load(file_path=config_file)
76
+
77
+ # run the tests
78
+ its.test(test_config=config)
79
+
80
+
81
+ ```
82
+
83
+ ### Configs
84
+ Tests are run based on configurations. The following is an example of supported configurations:
85
+
86
+ - Appliction Configuration Settings
87
+ - Logins & Access
88
+ - Executing an Analysis
89
+ - Running a Validation
90
+
91
+ ```json
92
+ {
93
+ "application_config_test": {
94
+ "purpose": "Tests the application configuration endpoints",
95
+ "hosts": [
96
+ {
97
+ "host": "api.example.com",
98
+ "expected_results": {
99
+ "status_code": 200
100
+ },
101
+ "enabled": true
102
+ },
103
+ {
104
+ "host": "XXXXXXXXXXXXXXXXXXXXX",
105
+ "expected_results": {
106
+ "status_code": 403
107
+ },
108
+ "enabled": false
109
+ }
110
+ ]
111
+ },
112
+ "login_test": {
113
+ "purpose": "Tests the login endpoints",
114
+ "logins": [
115
+ {
116
+ "username": "foo",
117
+ "password": "barr",
118
+ "host": "api.example.com",
119
+ "roles": []
120
+ },
121
+ {
122
+ "username": "XXXXXXXXXXXXXXXXXXXXX",
123
+ "password": "XXXXXXXXXXXXXXXXXXXXX",
124
+ "host": "XXXXXXXXXXXXXXXXXXXXX",
125
+ "roles": [
126
+ "XXXXXXXXXXXXXXXXXXXXX"
127
+ ],
128
+ "enabled": false,
129
+ "expected_results": {
130
+ "exception": "InvalidCredentialsException"
131
+ }
132
+ }
133
+ ]
134
+ },
135
+ "file_upload_test": {
136
+ "purpose": "Tests the file upload endpoints.",
137
+ "notes": "a file can be on the local drive or pulled from a public https source.",
138
+ "login": {
139
+ "purpose": "optional: if present this login is used, unless a specific login is defined for the test",
140
+ "username": "foo",
141
+ "password": "bar",
142
+ "host": "api.example.com"
143
+ },
144
+ "files": [
145
+ {
146
+ "file": "XXXXXXXXXXXXXXXXXXXXX"
147
+ },
148
+ {
149
+ "file": "XXXXXXXXXXXXXXXXXXXXX",
150
+ "login": {
151
+ "purpose": "optional: if present tests an upload for a specific user",
152
+ "username": "XXXXXXXXXXXXXXXXXXXXX",
153
+ "password": "XXXXXXXXXXXXXXXXXXXXX",
154
+ "host": "XXXXXXXXXXXXXXXXXXXXX"
155
+ }
156
+ }
157
+ ]
158
+ },
159
+ "analysis_execution_test": {
160
+ "purpose": "Tests the analysis execution endpoints.",
161
+ "login": {
162
+ "username": "XXXXXXXXXXXXXXXXXXXXX",
163
+ "password": "XXXXXXXXXXXXXXXXXXXXX",
164
+ "host": "XXXXXXXXXXXXXXXXXXXXX"
165
+ },
166
+ "output_dir": "XXXXXXXXXXXXXXXXXXXXX",
167
+ "analyses": [
168
+ {
169
+ "file": "XXXXXXXXXXXXXXXXXXXXX",
170
+ "meta": {},
171
+ "config": {},
172
+ "expected_results": {
173
+ "status_code": 200
174
+ },
175
+ "output_dir": "XXXXXXXXXXXXXXXXXXXXX"
176
+ },
177
+ {
178
+ "file": "XXXXXXXXXXXXXXXXXXXXX",
179
+ "meta": {},
180
+ "config": {},
181
+ "login": {
182
+ "username": "XXXXXXXXXXXXXXXXXXXXX",
183
+ "password": "XXXXXXXXXXXXXXXXXXXXX",
184
+ "host": "XXXXXXXXXXXXXXXXXXXXX"
185
+ },
186
+ "expected_results": {
187
+ "status_code": 200
188
+ }
189
+ }
190
+ ]
191
+ },
192
+ "validation_test": {
193
+ "purpose": "Tests the validation execution.",
194
+ "login": {
195
+ "username": "XXXXXXXXXXXXXXXXXXXXX",
196
+ "password": "XXXXXXXXXXXXXXXXXXXXX",
197
+ "host": "XXXXXXXXXXXXXXXXXXXXX"
198
+ },
199
+ "expected_results": {
200
+ "status_code": 200
201
+ }
202
+ }
203
+ }
204
+
205
+ ```
@@ -0,0 +1,62 @@
1
+ """
2
+ Copyright 2024-2025 Aplos Analytics
3
+ All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
4
+ Property of Aplos Analytics, Utah, USA
5
+ """
6
+
7
+ from aws_lambda_powertools import Logger
8
+
9
+ from aplos_nca_saas_sdk.integration_testing.integration_test_base import (
10
+ IntegrationTestBase,
11
+ )
12
+ from aplos_nca_saas_sdk.integration_testing.integration_test_response import (
13
+ IntegrationTestResponse,
14
+ )
15
+ from aplos_nca_saas_sdk.nca_resources.nca_validations import NCAValidation
16
+
17
+
18
+ logger = Logger(service="NCAAnalysisValidationTest")
19
+
20
+
21
+ class NCAAnalysisValidationTest(IntegrationTestBase):
22
+ """NCA Validation Test Container"""
23
+
24
+ def __init__(self):
25
+ super().__init__("nca-validation")
26
+
27
+ def test(self) -> bool:
28
+ """Test Engine Validation"""
29
+
30
+ self.results.clear()
31
+
32
+ for config in self.config.nca_validations.list:
33
+ test_response: IntegrationTestResponse = IntegrationTestResponse()
34
+ test_response.name = self.name
35
+
36
+ try:
37
+ # Create new NCA Execution
38
+ nca_validation: NCAValidation = NCAValidation(config.login.host)
39
+
40
+ # Initialize Configuration Data
41
+
42
+ # Execute, the execution should raise errors that will fail the test
43
+ logger.info({"message": "Invoking Execution"})
44
+ execution_response = nca_validation.execute(
45
+ username=config.login.username,
46
+ password=config.login.password,
47
+ wait_for_results=True,
48
+ )
49
+
50
+ # Verify Download
51
+ logger.info({"message": "Validation complete. Verifying results."})
52
+
53
+ pass_fail = execution_response.get("results", {}).get("pass_fail")
54
+ if pass_fail != "pass":
55
+ raise RuntimeError("One or more validations failed.")
56
+
57
+ except Exception as e: # pylint: disable=w0718
58
+ test_response.error = str(e)
59
+
60
+ self.results.append(test_response)
61
+
62
+ return self.success()
@@ -150,7 +150,7 @@ class NCAAnalysis(NCAApiBaseClass):
150
150
  raise ValueError(
151
151
  "Missing config_data. Please provide a valid config_data."
152
152
  )
153
- headers = HttpUtilities.get_headers(self.authenticator.cognito.jwt)
153
+ headers = self.authenticator.get_jwt_http_headers()
154
154
  # to start a new execution we need the location of the file (s3 bucket and object key)
155
155
  # you basic configuration
156
156
  # optional meta data
@@ -9,6 +9,7 @@ from aplos_nca_saas_sdk.nca_resources.aws_cognito import CognitoAuthentication
9
9
  from aplos_nca_saas_sdk.nca_resources.nca_app_configuration import (
10
10
  NCAAppConfiguration,
11
11
  )
12
+ from aplos_nca_saas_sdk.utilities.http_utility import HttpUtilities
12
13
 
13
14
 
14
15
  class NCAAuthenticator:
@@ -105,3 +106,7 @@ class NCAAuthenticator:
105
106
  self.cognito.login(username=username, password=password)
106
107
 
107
108
  return self.cognito.jwt
109
+
110
+ def get_jwt_http_headers(self) -> str:
111
+ """Get the formatted http headers for the JWT"""
112
+ return HttpUtilities.get_headers(self.cognito.jwt)
@@ -70,6 +70,10 @@ class NCAEndpoints:
70
70
  """Returns the validations endpoint"""
71
71
  return f"{self.user_path}/nca/validations"
72
72
 
73
+ def validation(self, batch_id: str) -> str:
74
+ """Returns the validations endpoint for a specific batch"""
75
+ return f"{self.validations}/{batch_id}"
76
+
73
77
  @property
74
78
  def files(self) -> str:
75
79
  """Returns the files endpoint"""
@@ -0,0 +1,101 @@
1
+ """
2
+ Copyright 2024-2025 Aplos Analytics
3
+ All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
4
+ Property of Aplos Analytics, Utah, USA
5
+ """
6
+
7
+ import time
8
+ from datetime import datetime, timedelta
9
+ from typing import Any, Dict
10
+
11
+ import requests
12
+ from aws_lambda_powertools import Logger
13
+ from aplos_nca_saas_sdk.nca_resources._api_base import NCAApiBaseClass
14
+
15
+ logger = Logger(service="nca-validations")
16
+
17
+
18
+ class NCAValidation(NCAApiBaseClass):
19
+ """NCA Analysis Validation API"""
20
+
21
+ def __init__(self, host: str) -> None:
22
+ super().__init__(host)
23
+
24
+ def execute(
25
+ self,
26
+ username: str,
27
+ password: str,
28
+ wait_for_results: bool = True,
29
+ max_wait_in_seconds: int = 900,
30
+ ) -> Dict[str, Any]:
31
+ """
32
+ Runs a validation
33
+
34
+ Args:
35
+ username (str): username
36
+ password (str): password
37
+
38
+ Returns:
39
+ Dict[str, Any]: response object
40
+ """
41
+
42
+ self.authenticator.authenticate(username=username, password=password)
43
+ url = self.endpoints.validations
44
+ # no payload required
45
+ headers = self.authenticator.get_jwt_http_headers()
46
+ validation_post_response = requests.post(url, headers=headers, timeout=30)
47
+
48
+ if validation_post_response.status_code != 200:
49
+ raise RuntimeError(
50
+ f"Failed to execution a validation batch. Status Code: {validation_post_response.status_code}"
51
+ f"Reason: {validation_post_response.reason}"
52
+ )
53
+
54
+ response = {
55
+ "queued": validation_post_response.json(),
56
+ "results": None,
57
+ }
58
+
59
+ if wait_for_results:
60
+ batch_id = (
61
+ validation_post_response.json().get("validation_batch", {}).get("id")
62
+ )
63
+
64
+ if not batch_id:
65
+ raise RuntimeError(
66
+ "Failed to get the validation batch id from the response."
67
+ )
68
+ completed = False
69
+ current_time = datetime.now()
70
+ # Create a timedelta object representing 15 minutes
71
+ time_delta = timedelta(seconds=max_wait_in_seconds)
72
+ # Add the timedelta to the current time
73
+ max_time = current_time + time_delta
74
+ while not completed:
75
+ validation_get_response = requests.get(
76
+ self.endpoints.validation(batch_id=batch_id),
77
+ timeout=30,
78
+ headers=self.authenticator.get_jwt_http_headers(),
79
+ )
80
+ if validation_get_response.status_code != 200:
81
+ raise RuntimeError(
82
+ f"Failed to get validation results. Status Code: {validation_get_response.status_code}"
83
+ f"Reason: {validation_get_response.reason}"
84
+ )
85
+ status = validation_get_response.json().get("status")
86
+ completed = status == "complete"
87
+
88
+ if not completed:
89
+ if datetime.now() > max_time:
90
+ raise RuntimeError(
91
+ "Timeout attempting to get validation results. "
92
+ f"The current timeout limit is {max_wait_in_seconds} seconds. "
93
+ "You may need to up the timeout period, or check for errors. "
94
+ )
95
+ logger.info(f"waiting for results.... {status}")
96
+ time.sleep(15)
97
+ else:
98
+ response["results"] = validation_get_response.json()
99
+
100
+ logger.info("Validation complete.")
101
+ return response
@@ -1,4 +1,4 @@
1
1
  # Aplos NCA SaaS SDK Version File
2
2
  # This is automatically generated during the build process.
3
3
  # DO NOT UPDATE IT DIRECTLY. IT WILL BE OVERWRITTEN.
4
- __version__ = '0.0.14'
4
+ __version__ = '0.0.16'
@@ -1,18 +0,0 @@
1
- # Integration Test
2
-
3
- This module runs integration tests against a live environment. The goal is to catch anything before it's deployed.
4
- However you can also use this as a learning tool or a base on how to use our API's.
5
-
6
- ## Requirements
7
- The integration tests will require the following:
8
-
9
- ### Environment Vars
10
- |Variable Name|Description|
11
- |--|--|
12
- |APLOS_host|The full host name. e.g. app.aplos-nca.com|
13
-
14
-
15
- ### Users
16
- You will need valid user accounts with the appropriate permissions for the endpoints they are executing.
17
-
18
- If you are testing permission bounderies then you should set up multiple users with different permissions.
@@ -1,5 +0,0 @@
1
- """
2
- Copyright 2024-2025 Aplos Analytics
3
- All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
4
- Property of Aplos Analytics, Utah, USA
5
- """
@@ -1,34 +0,0 @@
1
- """
2
- Copyright 2024-2025 Aplos Analytics
3
- All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
4
- Property of Aplos Analytics, Utah, USA
5
- """
6
-
7
- import requests
8
-
9
- from aplos_nca_saas_sdk.nca_resources._api_base import NCAApiBaseClass
10
-
11
-
12
- class NCAValidation(NCAApiBaseClass):
13
- """NCA Analysis Validation API"""
14
-
15
- def __init__(self, host: str) -> None:
16
- super().__init__(host)
17
-
18
- def validate(self, jwt: str) -> bool:
19
- """
20
- Validates the JWT
21
-
22
- Args:
23
- jwt (str): JWT
24
-
25
- Returns:
26
- bool: True if the JWT is valid
27
- """
28
- url = self.endpoints.validations
29
- response = requests.post(url, json={"jwt": jwt}, timeout=30)
30
-
31
- if response.status_code != 200:
32
- return False
33
-
34
- return True