First of all, please read the introduction of the creators: Introduction to Active Data and the definition of what a REALM is in active-data: REALMS in active-data. This is necessary to understand the following.
Here, active-data will be seen from the perspective of testing programs. In contrast to a data representation via a key-value map or pure dynamic typing, records, functions, and other types are strictly defined by active-data realms. As a result, the types and data structures are well defined and visible in the source code. There is no way to create a record or a function in a way that does not meet the requirements of the active-data realm definition. This is true for sets of a specific type, maps with specific key/value types, enums, records, and functions. This strict definition improves testability because a test framework can read the data's specific contracts and attributes. For example, a test can see whether an integer range or an enum is defined and which values are valid. You no longer need to test a function with every possible value to see whether unwanted values return a well-defined result. The result of an unwanted value is defined by active data. So testing can focus on the valid data range to verify the logic. Testing parameter and return-value validity is complex and time-consuming, and if you don't need to test it further, you have many other things to test.
What has to be tested for the incoming parameters is, for example, the relation of the values of a parameter in relation to the values of the other parameters given in the same call of a function. If realm/intersection and realm/union are used, possibly in connection with realm/restricted, such things can also be expressed with active-data.
To get input for tests, the active-data meta information can be retrieved from the data objects or functions. This can be used to get all information about the interfaces of functions, records, and other data objects.
Like Java reflection, we have all the information we need to create tests that cover all combinations needed for very high coverage. The same is valid when generating test data.
Since we talk about data-oriented programming and design, it is fair to call this data-oriented testing, because input data from reflection, user-defined contracts, and data layouts drive test definitions and test data generation.
data-oriented testing in YATestEnvironmentIn short, Data-oriented testing is a testing approach in which tests and test data are defined and generated automatically by analyzing reflected productive functions and using user-defined use cases, data formats, data source definitions, and data flow plans. One part of the tests can be generated and executed dynamically, and the test results can be logged in detail. This part focuses on testing functionality with different kinds of test data. The other part includes tests that run strict checks on the production code for regression and new functionality. These tests store results to ensure repeatable, verifiable outcomes.
It's called data-oriented because it collects different kinds of data. The code treats reflection results as input data for testing and test data generation. Use cases are another data input that distinguishes test assertions and test control flow from test data input and input sources. The test code is generated so input data controls the flow, so the test code changes only if the business logic or general interfaces change. The tests and control flow are defined in a Test Matrix and a Test Steps Definition; together, these define the test logic and input data.
In the following Clojure example, I show the principles of this testing approach. To see how it is realized effectively in the project, see the
