genlayer-test 0.7.0__tar.gz → 0.8.0__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 (87) hide show
  1. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/PKG-INFO +217 -3
  2. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/README.md +215 -1
  3. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/genlayer_test.egg-info/PKG-INFO +217 -3
  4. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/genlayer_test.egg-info/SOURCES.txt +3 -0
  5. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/genlayer_test.egg-info/requires.txt +1 -1
  6. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/__init__.py +3 -0
  7. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/types.py +12 -1
  8. genlayer_test-0.8.0/gltest/validators/__init__.py +3 -0
  9. genlayer_test-0.8.0/gltest/validators/validator_factory.py +136 -0
  10. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/pyproject.toml +2 -2
  11. genlayer_test-0.8.0/tests/examples/tests/test_custom_validators.py +65 -0
  12. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/LICENSE +0 -0
  13. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/genlayer_test.egg-info/dependency_links.txt +0 -0
  14. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/genlayer_test.egg-info/entry_points.txt +0 -0
  15. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/genlayer_test.egg-info/top_level.txt +0 -0
  16. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/accounts.py +0 -0
  17. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/artifacts/__init__.py +0 -0
  18. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/artifacts/contract.py +0 -0
  19. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/assertions.py +0 -0
  20. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/clients.py +0 -0
  21. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/contracts/__init__.py +0 -0
  22. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/contracts/contract.py +0 -0
  23. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/contracts/contract_factory.py +0 -0
  24. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/contracts/contract_functions.py +0 -0
  25. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/contracts/method_stats.py +0 -0
  26. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/contracts/stats_collector.py +0 -0
  27. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/contracts/utils.py +0 -0
  28. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/exceptions.py +0 -0
  29. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/fixtures.py +0 -0
  30. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/helpers/__init__.py +0 -0
  31. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/helpers/fixture_snapshot.py +0 -0
  32. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/helpers/take_snapshot.py +0 -0
  33. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/logging.py +0 -0
  34. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/utils.py +0 -0
  35. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/config/__init__.py +0 -0
  36. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/config/constants.py +0 -0
  37. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/config/general.py +0 -0
  38. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/config/plugin.py +0 -0
  39. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/config/pytest_context.py +0 -0
  40. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/config/types.py +0 -0
  41. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/config/user.py +0 -0
  42. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/logging.py +0 -0
  43. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/main.py +0 -0
  44. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/setup.cfg +0 -0
  45. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/__init__.py +0 -0
  46. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/conftest.py +0 -0
  47. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/football_prediction_market.py +0 -0
  48. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/intelligent_oracle.py +0 -0
  49. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/intelligent_oracle_factory.py +0 -0
  50. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/invalid_deploy.py +0 -0
  51. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/llm_erc20.py +0 -0
  52. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/log_indexer.py +0 -0
  53. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/multi_file_contract/__init__.py +0 -0
  54. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/multi_file_contract/other.py +0 -0
  55. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/multi_read_erc20.py +0 -0
  56. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/multi_tenant_storage.py +0 -0
  57. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/read_erc20.py +0 -0
  58. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/simple_time_contract.py +0 -0
  59. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/storage.py +0 -0
  60. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/user_storage.py +0 -0
  61. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/wizard_of_coin.py +0 -0
  62. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_football_prediction_market.py +0 -0
  63. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_intelligent_oracle_factory.py +0 -0
  64. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_invalid_deploy.py +0 -0
  65. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_llm_erc20.py +0 -0
  66. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_llm_erc20_analyze.py +0 -0
  67. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_log_indexer.py +0 -0
  68. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_multi_file_contract.py +0 -0
  69. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_multi_read_erc20.py +0 -0
  70. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_multi_tenant_storage.py +0 -0
  71. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_read_erc20.py +0 -0
  72. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_simple_time_contract.py +0 -0
  73. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_storage.py +0 -0
  74. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_user_storage.py +0 -0
  75. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_wizard_of_coin.py +0 -0
  76. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest/__init__.py +0 -0
  77. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest/artifact/__init__.py +0 -0
  78. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest/artifact/contracts/duplicate_ic_contract_1.py +0 -0
  79. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest/artifact/contracts/duplicate_ic_contract_2.py +0 -0
  80. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest/artifact/contracts/not_ic_contract.py +0 -0
  81. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest/artifact/test_contract_definition.py +0 -0
  82. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest/assertions/test_assertions.py +0 -0
  83. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest_cli/__init__.py +0 -0
  84. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest_cli/config/test_config_integration.py +0 -0
  85. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest_cli/config/test_general_config.py +0 -0
  86. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest_cli/config/test_plugin.py +0 -0
  87. {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest_cli/config/test_user.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: genlayer-test
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: GenLayer Testing Suite
5
5
  Author: GenLayer
6
6
  License-Expression: MIT
@@ -15,7 +15,7 @@ Description-Content-Type: text/markdown
15
15
  License-File: LICENSE
16
16
  Requires-Dist: pytest
17
17
  Requires-Dist: setuptools>=77.0
18
- Requires-Dist: genlayer-py==0.8.1
18
+ Requires-Dist: genlayer-py==0.9.0
19
19
  Requires-Dist: colorama>=0.4.6
20
20
  Requires-Dist: pyyaml
21
21
  Requires-Dist: python-dotenv
@@ -308,6 +308,7 @@ When this flag is enabled, all contracts deployed and all write transactions wil
308
308
  - **State Injection & Consensus Simulation** – Modify contract states dynamically and simulate consensus scenarios for advanced testing.
309
309
  - **Prompt Testing & Statistical Analysis** – Evaluate and statistically test prompts for AI-driven contract execution.
310
310
  - **Scalability to Security & Audit Tools** – Designed to extend into security testing and smart contract auditing.
311
+ - **Custom Transaction Context** – Set custom validators with specific LLM providers and models, and configure GenVM datetime for deterministic testing scenarios.
311
312
 
312
313
  ## 📚 Examples
313
314
 
@@ -387,6 +388,7 @@ def test_deployment():
387
388
  args=["initial_value"], # Constructor arguments
388
389
  account=get_default_account(), # Account to deploy from
389
390
  consensus_max_rotations=3, # Optional: max consensus rotations
391
+ transaction_context=None, # Optional: custom transaction context
390
392
  )
391
393
 
392
394
  # Contract is now deployed and ready to use
@@ -419,7 +421,9 @@ def test_read_methods():
419
421
  contract = factory.deploy()
420
422
 
421
423
  # Call a read-only method
422
- result = contract.get_storage(args=[]).call()
424
+ result = contract.get_storage(args=[]).call(
425
+ transaction_context=None, # Optional: custom transaction context
426
+ )
423
427
 
424
428
  # Assert the result matches the initial value
425
429
  assert result == "initial_value"
@@ -446,6 +450,7 @@ def test_write_methods():
446
450
  consensus_max_rotations=3, # Optional: max consensus rotations
447
451
  wait_interval=1, # Optional: seconds between status checks
448
452
  wait_retries=10, # Optional: max number of retries
453
+ transaction_context=None, # Optional: custom transaction context
449
454
  )
450
455
 
451
456
  # Verify the transaction was successful
@@ -609,6 +614,7 @@ def test_analyze_method():
609
614
  config=None, # Optional: provider-specific config
610
615
  plugin=None, # Optional: plugin name
611
616
  plugin_config=None, # Optional: plugin configuration
617
+ genvm_datetime="2024-01-15T10:30:00Z", # Optional: GenVM datetime in ISO format
612
618
  )
613
619
 
614
620
  # Access analysis results
@@ -757,6 +763,214 @@ def test_with_mocked_llm(setup_validators):
757
763
  - The `setup_validators` fixture handles the mock setup when provided with a mock_response
758
764
  - Mocking is particularly useful for CI/CD pipelines where deterministic results are required
759
765
 
766
+ ### Custom Transaction Context
767
+
768
+ The GenLayer Testing Suite allows you to customize the transaction execution environment by providing a `transaction_context` parameter with custom validators and GenVM datetime settings.
769
+
770
+ #### Using Transaction Context
771
+
772
+ Set custom validators and GenVM datetime for deterministic testing:
773
+
774
+ ```python
775
+ from gltest import get_contract_factory, get_validator_factory
776
+
777
+ def test_with_custom_transaction_context():
778
+ factory = get_contract_factory("MyContract")
779
+ validator_factory = get_validator_factory()
780
+
781
+ # Create custom validators
782
+ validators = validator_factory.batch_create_validators(
783
+ count=3,
784
+ stake=10,
785
+ provider="openai",
786
+ model="gpt-4o",
787
+ config={"temperature": 0.7, "max_tokens": 1000},
788
+ plugin="openai-compatible",
789
+ plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
790
+ )
791
+
792
+ # Create transaction context with custom validators and datetime
793
+ transaction_context = {
794
+ "validators": [v.to_dict() for v in validators],
795
+ "genvm_datetime": "2024-03-15T14:30:00Z" # ISO format datetime
796
+ }
797
+
798
+ # Deploy with custom context
799
+ contract = factory.deploy(
800
+ args=["initial_value"],
801
+ transaction_context=transaction_context
802
+ )
803
+
804
+ # Call methods with custom context
805
+ result = contract.read_method().call(
806
+ transaction_context=transaction_context
807
+ )
808
+
809
+ # Write operations with custom context
810
+ tx_receipt = contract.write_method(args=["value"]).transact(
811
+ transaction_context=transaction_context
812
+ )
813
+ ```
814
+
815
+ #### Mock Validators with Transaction Context
816
+
817
+ Combine mock validators with custom datetime for fully deterministic tests:
818
+
819
+ ```python
820
+ def test_with_mocked_context():
821
+ factory = get_contract_factory("LLMContract")
822
+ validator_factory = get_validator_factory()
823
+
824
+ # Define mock LLM responses
825
+ mock_response = {
826
+ "nondet_exec_prompt": {
827
+ "analyze this": "positive sentiment"
828
+ },
829
+ "eq_principle_prompt_comparative": {
830
+ "values match": True
831
+ }
832
+ }
833
+
834
+ # Create mock validators
835
+ mock_validators = validator_factory.batch_create_mock_validators(
836
+ count=5,
837
+ mock_llm_response=mock_response
838
+ )
839
+
840
+ # Set up deterministic context
841
+ transaction_context = {
842
+ "validators": [v.to_dict() for v in mock_validators],
843
+ "genvm_datetime": "2024-01-01T00:00:00Z" # Fixed datetime for reproducibility
844
+ }
845
+
846
+ # Deploy and test with deterministic context
847
+ contract = factory.deploy(transaction_context=transaction_context)
848
+
849
+ # All operations will use the same mocked validators and datetime
850
+ result = contract.analyze_text(args=["analyze this"]).transact(
851
+ transaction_context=transaction_context
852
+ )
853
+ # Result will consistently return "positive sentiment"
854
+ ```
855
+
856
+ ### Custom Validators
857
+
858
+ The GenLayer Testing Suite includes a `get_validator_factory()` function that allows you to create custom validators with specific configurations for testing different LLM providers and consensus scenarios.
859
+
860
+ #### Creating Custom Validators
861
+
862
+ ```python
863
+ from gltest import get_validator_factory
864
+
865
+ def test_with_custom_validators():
866
+ factory = get_validator_factory()
867
+
868
+ # Create validators with different LLM providers
869
+ openai_validator = factory.create_validator(
870
+ stake=10,
871
+ provider="openai",
872
+ model="gpt-4o",
873
+ config={"temperature": 0.8, "max_tokens": 2000},
874
+ plugin="openai-compatible",
875
+ plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
876
+ )
877
+
878
+ ollama_validator = factory.create_validator(
879
+ stake=8,
880
+ provider="ollama",
881
+ model="mistral",
882
+ config={"temperature": 0.5},
883
+ plugin="ollama",
884
+ plugin_config={"api_url": "http://localhost:11434"}
885
+ )
886
+
887
+ # Use validators in your tests
888
+ validators = [openai_validator, ollama_validator]
889
+ # Configure your test environment with these validators
890
+ ```
891
+
892
+ #### Batch Creation
893
+
894
+ Create multiple validators with the same configuration:
895
+
896
+ ```python
897
+ def test_batch_validators():
898
+ factory = get_validator_factory()
899
+
900
+ # Create 5 validators with identical configuration
901
+ validators = factory.batch_create_validators(
902
+ count=5,
903
+ stake=8,
904
+ provider="openai",
905
+ model="gpt-4o",
906
+ config={"temperature": 0.7, "max_tokens": 1000},
907
+ plugin="openai-compatible",
908
+ plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
909
+ )
910
+ ```
911
+
912
+ #### Mock Validators
913
+
914
+ For deterministic testing, create mock validators that return predefined responses:
915
+
916
+ ```python
917
+ def test_with_mock_validators():
918
+ factory = get_validator_factory()
919
+
920
+ # Define mock responses
921
+ mock_response = {
922
+ "nondet_exec_prompt": {
923
+ "What is 2+2?": "4",
924
+ "Explain quantum physics": "It's complicated"
925
+ },
926
+ "eq_principle_prompt_comparative": {
927
+ "values must match": True
928
+ },
929
+ "eq_principle_prompt_non_comparative": {
930
+ "Is this valid?": True
931
+ }
932
+ }
933
+
934
+ # Create a single mock validator
935
+ mock_validator = factory.create_mock_validator(mock_response)
936
+
937
+ # Create multiple mock validators
938
+ mock_validators = factory.batch_create_mock_validators(
939
+ count=5,
940
+ mock_llm_response=mock_response
941
+ )
942
+ ```
943
+
944
+ #### Validator Methods
945
+
946
+ Each validator object provides useful methods:
947
+ - `to_dict()`: Convert validator to dictionary format for API calls
948
+ - `clone()`: Create an identical copy of the validator
949
+ - `batch_clone(count)`: Create multiple identical copies
950
+
951
+ Example:
952
+ ```python
953
+ def test_validator_cloning():
954
+ factory = get_validator_factory()
955
+
956
+ # Create a base validator
957
+ base_validator = factory.create_validator(
958
+ stake=10,
959
+ provider="openai",
960
+ model="gpt-4o",
961
+ config={"temperature": 0.7},
962
+ plugin="openai-compatible",
963
+ plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
964
+ )
965
+
966
+ # Clone it to create identical validators
967
+ cloned = base_validator.clone()
968
+ multiple_clones = base_validator.batch_clone(3)
969
+
970
+ # Convert to dictionary for API usage
971
+ validator_dict = base_validator.to_dict()
972
+ ```
973
+
760
974
  ## 📝 Best Practices
761
975
 
762
976
  1. **Test Organization**
@@ -285,6 +285,7 @@ When this flag is enabled, all contracts deployed and all write transactions wil
285
285
  - **State Injection & Consensus Simulation** – Modify contract states dynamically and simulate consensus scenarios for advanced testing.
286
286
  - **Prompt Testing & Statistical Analysis** – Evaluate and statistically test prompts for AI-driven contract execution.
287
287
  - **Scalability to Security & Audit Tools** – Designed to extend into security testing and smart contract auditing.
288
+ - **Custom Transaction Context** – Set custom validators with specific LLM providers and models, and configure GenVM datetime for deterministic testing scenarios.
288
289
 
289
290
  ## 📚 Examples
290
291
 
@@ -364,6 +365,7 @@ def test_deployment():
364
365
  args=["initial_value"], # Constructor arguments
365
366
  account=get_default_account(), # Account to deploy from
366
367
  consensus_max_rotations=3, # Optional: max consensus rotations
368
+ transaction_context=None, # Optional: custom transaction context
367
369
  )
368
370
 
369
371
  # Contract is now deployed and ready to use
@@ -396,7 +398,9 @@ def test_read_methods():
396
398
  contract = factory.deploy()
397
399
 
398
400
  # Call a read-only method
399
- result = contract.get_storage(args=[]).call()
401
+ result = contract.get_storage(args=[]).call(
402
+ transaction_context=None, # Optional: custom transaction context
403
+ )
400
404
 
401
405
  # Assert the result matches the initial value
402
406
  assert result == "initial_value"
@@ -423,6 +427,7 @@ def test_write_methods():
423
427
  consensus_max_rotations=3, # Optional: max consensus rotations
424
428
  wait_interval=1, # Optional: seconds between status checks
425
429
  wait_retries=10, # Optional: max number of retries
430
+ transaction_context=None, # Optional: custom transaction context
426
431
  )
427
432
 
428
433
  # Verify the transaction was successful
@@ -586,6 +591,7 @@ def test_analyze_method():
586
591
  config=None, # Optional: provider-specific config
587
592
  plugin=None, # Optional: plugin name
588
593
  plugin_config=None, # Optional: plugin configuration
594
+ genvm_datetime="2024-01-15T10:30:00Z", # Optional: GenVM datetime in ISO format
589
595
  )
590
596
 
591
597
  # Access analysis results
@@ -734,6 +740,214 @@ def test_with_mocked_llm(setup_validators):
734
740
  - The `setup_validators` fixture handles the mock setup when provided with a mock_response
735
741
  - Mocking is particularly useful for CI/CD pipelines where deterministic results are required
736
742
 
743
+ ### Custom Transaction Context
744
+
745
+ The GenLayer Testing Suite allows you to customize the transaction execution environment by providing a `transaction_context` parameter with custom validators and GenVM datetime settings.
746
+
747
+ #### Using Transaction Context
748
+
749
+ Set custom validators and GenVM datetime for deterministic testing:
750
+
751
+ ```python
752
+ from gltest import get_contract_factory, get_validator_factory
753
+
754
+ def test_with_custom_transaction_context():
755
+ factory = get_contract_factory("MyContract")
756
+ validator_factory = get_validator_factory()
757
+
758
+ # Create custom validators
759
+ validators = validator_factory.batch_create_validators(
760
+ count=3,
761
+ stake=10,
762
+ provider="openai",
763
+ model="gpt-4o",
764
+ config={"temperature": 0.7, "max_tokens": 1000},
765
+ plugin="openai-compatible",
766
+ plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
767
+ )
768
+
769
+ # Create transaction context with custom validators and datetime
770
+ transaction_context = {
771
+ "validators": [v.to_dict() for v in validators],
772
+ "genvm_datetime": "2024-03-15T14:30:00Z" # ISO format datetime
773
+ }
774
+
775
+ # Deploy with custom context
776
+ contract = factory.deploy(
777
+ args=["initial_value"],
778
+ transaction_context=transaction_context
779
+ )
780
+
781
+ # Call methods with custom context
782
+ result = contract.read_method().call(
783
+ transaction_context=transaction_context
784
+ )
785
+
786
+ # Write operations with custom context
787
+ tx_receipt = contract.write_method(args=["value"]).transact(
788
+ transaction_context=transaction_context
789
+ )
790
+ ```
791
+
792
+ #### Mock Validators with Transaction Context
793
+
794
+ Combine mock validators with custom datetime for fully deterministic tests:
795
+
796
+ ```python
797
+ def test_with_mocked_context():
798
+ factory = get_contract_factory("LLMContract")
799
+ validator_factory = get_validator_factory()
800
+
801
+ # Define mock LLM responses
802
+ mock_response = {
803
+ "nondet_exec_prompt": {
804
+ "analyze this": "positive sentiment"
805
+ },
806
+ "eq_principle_prompt_comparative": {
807
+ "values match": True
808
+ }
809
+ }
810
+
811
+ # Create mock validators
812
+ mock_validators = validator_factory.batch_create_mock_validators(
813
+ count=5,
814
+ mock_llm_response=mock_response
815
+ )
816
+
817
+ # Set up deterministic context
818
+ transaction_context = {
819
+ "validators": [v.to_dict() for v in mock_validators],
820
+ "genvm_datetime": "2024-01-01T00:00:00Z" # Fixed datetime for reproducibility
821
+ }
822
+
823
+ # Deploy and test with deterministic context
824
+ contract = factory.deploy(transaction_context=transaction_context)
825
+
826
+ # All operations will use the same mocked validators and datetime
827
+ result = contract.analyze_text(args=["analyze this"]).transact(
828
+ transaction_context=transaction_context
829
+ )
830
+ # Result will consistently return "positive sentiment"
831
+ ```
832
+
833
+ ### Custom Validators
834
+
835
+ The GenLayer Testing Suite includes a `get_validator_factory()` function that allows you to create custom validators with specific configurations for testing different LLM providers and consensus scenarios.
836
+
837
+ #### Creating Custom Validators
838
+
839
+ ```python
840
+ from gltest import get_validator_factory
841
+
842
+ def test_with_custom_validators():
843
+ factory = get_validator_factory()
844
+
845
+ # Create validators with different LLM providers
846
+ openai_validator = factory.create_validator(
847
+ stake=10,
848
+ provider="openai",
849
+ model="gpt-4o",
850
+ config={"temperature": 0.8, "max_tokens": 2000},
851
+ plugin="openai-compatible",
852
+ plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
853
+ )
854
+
855
+ ollama_validator = factory.create_validator(
856
+ stake=8,
857
+ provider="ollama",
858
+ model="mistral",
859
+ config={"temperature": 0.5},
860
+ plugin="ollama",
861
+ plugin_config={"api_url": "http://localhost:11434"}
862
+ )
863
+
864
+ # Use validators in your tests
865
+ validators = [openai_validator, ollama_validator]
866
+ # Configure your test environment with these validators
867
+ ```
868
+
869
+ #### Batch Creation
870
+
871
+ Create multiple validators with the same configuration:
872
+
873
+ ```python
874
+ def test_batch_validators():
875
+ factory = get_validator_factory()
876
+
877
+ # Create 5 validators with identical configuration
878
+ validators = factory.batch_create_validators(
879
+ count=5,
880
+ stake=8,
881
+ provider="openai",
882
+ model="gpt-4o",
883
+ config={"temperature": 0.7, "max_tokens": 1000},
884
+ plugin="openai-compatible",
885
+ plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
886
+ )
887
+ ```
888
+
889
+ #### Mock Validators
890
+
891
+ For deterministic testing, create mock validators that return predefined responses:
892
+
893
+ ```python
894
+ def test_with_mock_validators():
895
+ factory = get_validator_factory()
896
+
897
+ # Define mock responses
898
+ mock_response = {
899
+ "nondet_exec_prompt": {
900
+ "What is 2+2?": "4",
901
+ "Explain quantum physics": "It's complicated"
902
+ },
903
+ "eq_principle_prompt_comparative": {
904
+ "values must match": True
905
+ },
906
+ "eq_principle_prompt_non_comparative": {
907
+ "Is this valid?": True
908
+ }
909
+ }
910
+
911
+ # Create a single mock validator
912
+ mock_validator = factory.create_mock_validator(mock_response)
913
+
914
+ # Create multiple mock validators
915
+ mock_validators = factory.batch_create_mock_validators(
916
+ count=5,
917
+ mock_llm_response=mock_response
918
+ )
919
+ ```
920
+
921
+ #### Validator Methods
922
+
923
+ Each validator object provides useful methods:
924
+ - `to_dict()`: Convert validator to dictionary format for API calls
925
+ - `clone()`: Create an identical copy of the validator
926
+ - `batch_clone(count)`: Create multiple identical copies
927
+
928
+ Example:
929
+ ```python
930
+ def test_validator_cloning():
931
+ factory = get_validator_factory()
932
+
933
+ # Create a base validator
934
+ base_validator = factory.create_validator(
935
+ stake=10,
936
+ provider="openai",
937
+ model="gpt-4o",
938
+ config={"temperature": 0.7},
939
+ plugin="openai-compatible",
940
+ plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
941
+ )
942
+
943
+ # Clone it to create identical validators
944
+ cloned = base_validator.clone()
945
+ multiple_clones = base_validator.batch_clone(3)
946
+
947
+ # Convert to dictionary for API usage
948
+ validator_dict = base_validator.to_dict()
949
+ ```
950
+
737
951
  ## 📝 Best Practices
738
952
 
739
953
  1. **Test Organization**