-
-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
End to End Testing #49
Comments
Partially implemented with #83 This only fires up an in memory sqlite database for godbledger. And also only a single test. To implement a test for the MySQL backend and load up with lots and lots of testing being sent to the server |
This is ongoing, currently in the The end goal is to get an end-to-end test suite where many concurrent instances are launched and many tests are fired in parallel. Defining these tests in a common format within a json file would allow for easy defining of tests. An example has been created in |
Made bulk updates to the integration tests, will now run multiple godbledger servers (3) and then runs a test in each one. These are not done in parallel currently and not sure how to make these do so yet. In the |
Todo items
|
e2e tests appear to be picking up configuration from my local installation (~/Library/ledger/config.toml) which is unexpected. the tests would be safer (i.e. more isolated and predictable) if they don't depend on or interact with any installation we may have running in the same environment. typically the way I have seen this achieved is to construct the tests in such a way that either (a) each test takes place in it's own sandboxed environment; or (b) a single sandboxed env is created for the test suite and reused (i.e. cleaned or reset before each individual test). the current e2e tests are doing some isolation (using a different port for each godbledger server process) but are not fully isolated (without passing the datadir or config file args they are picking up my default config file) that's the first thing I would look at adjusting, to complete the isolation of the test runs. second thing that I notice is that before we get to running tests in parallel, the e2e suite seems to start up 6 servers on 6 ports and then run 6 tests; I am not sure how this will scale so we may want to adjust how these are run such that each test runs in it's own complete space (data dir, config file, with mysql a unique temp data base or data file) and perhaps is executed as a batch with a configurable number of parallel tests. in this way new tests would queue up behind that bottleneck without consuming more and more ports/memory |
took another look at these integration tests. couple of observations:
I recommend that we update the func RunWithTestServer(t *testing.T, dbType string, index int, doWithServer func(*testing.T, string, *cmd.LedgerConfig)error) {
// clean and create data dir for dbType and test index
// invoke `cmd.MakeConfig` to build a configuration for the test data dir, dbType, and test index
// update the config as needed for the test database (e.g. to point to a mysql database)
// start the server and wait for it to be listening
// invoke `doWithServer`
// stop the server (e.g. kill the process)
// if test passed {
// clean up test directory (including log file and any database files)
// }
} The MySQL tests are interesting. The example using Github Actions referenced above (How to use a MySQL database on GitHub Actions) looks like it tells Github Actions to spin up a single MySQL database for an entire test run, which would not provide the same isolation between test evaluators as using a SQLite in-memory DB per test. Perhaps the MySQL tests could be updated to spin up a MySQL database inside docker (when running locally) and tagged differently (e.g. with |
as I've experimented with these changes a couple more observations:
|
Yeah the evaluator type could definitely be refined. The TransactorClient and transaction package is generated by GRPC though so its not really something we can add to. Its more that the test uses it as a client to talk to the server we spin up. I'm like the idea of having separate packages for the integration tests because I wasn't able to create build tags that separates mysql from sqlite when they are all in a single test package. Potentially the database modules would be good for this because each database is essentially drawing from our integration test cases (Evaluators) and running them against their backend. The config object is ugly as is right now, there is the so much repeated code. It passes flags to the server and also passes a config file which seems redundant. If there were separate packages this would probably be a single object passed to the tests package so it knows what to run, and that could be generated in the separate module. |
I did some reading on using build tags to separate tests with different constraints. The
which does get ignored unless the the tags appear to have conventions where commas are treated like
which would then run when the tags looked like this:
and not when they looked like this
so it looks like that part is actually working right now. I'm running into a different issue on my machine:
so I'm going to add a build tag there for the time being which separates each type of integration test |
use the integration tag for all the integration tests which should exclude them all when that tag is missing use a compound constraint to further segregate: - the mysql integration tests which are not yet working, they require additional investment to spin up a mysql db out-of-process; and - the secure connection tests which are failing on my machine, likely due to some OS-specific behavior around how the GRPC client behaves when connecting and validating certs: secure_connection_test.go:130: Node Version request failed: rpc error: code = Unavailable desc = connection error: desc = "transport: authentication handshake failed: x509: certificate is valid for 127.0.0.1, not 0.0.0.0"
use the integration tag for all the integration tests which should exclude them all when that tag is missing use a compound constraint to further segregate: - the mysql integration tests which are not yet working, they require additional investment to spin up a mysql db out-of-process; and - the secure connection tests which are failing on my machine, likely due to pollution of test context between tests and my local environment: secure_connection_test.go:130: Node Version request failed: rpc error: code = Unavailable desc = connection error: desc = "transport: authentication handshake failed: x509: certificate is valid for 127.0.0.1, not 0.0.0.0" after running the integration test suite I see the following untracked files: Untracked files: godbledger/rpc/~/ godbledger/~/ tests/~/ I notice that tests/~/Library/ledgerdb/config.toml contains configuration pointing to a data direction outside the source folder in my local home folder, which makes me uncertain which config is being used during the test for now I am segregating the secure tests in order to have a clean integration test run while I refactor the way test data, directory, and config is managed to improve isolation between test cases and the local environment
no point in running the mysql integration tests until they are actually testing the evaluators
thinking about the sqlite and mysql tests this morning, I'm struck by the orchestration differences between the in-memory sqlite pattern and the out-of-process mysql database. it seems that each backend may require its own approach to both setup and teardown. for a sqlite in-memory db setup can look like:
and teardown can look like:
but for a mysql database, let's say we spin up mysql in docker, are we spinning up and tearing down a new mysql database for each evaluation? maybe that makes sense, or maybe it makes sense to spin up a single mysql database container and run a set of tests against that backend, running db queries after each to clean them up? where this takes me is that it may not make sense to force both backend orchestrations into a single common abstraction. |
I'm thinking that there should be a common interface that can be implemented in both mysql and sqlite. It can maintain a pool of available servers that tests can be run using. Then we can queue our evaluators and it will grab a server from the pool if available, run the evaluator, cleanup and return the server to the pool. This way we can specify somewhere how many parallel servers we want to be able to support. so the interface would have functions like:
and it is up to each instance on how the add_server (also how to cleanup and return the server to the pool after a test) works. That way we have a place for each database to define its own lifecycle. For the mysql one it might mean we up a new database container and point the godbledger instance at that container, closing it down could just be a drop tables, create new database and restart godbledger |
I've stated compiling the files for there to be end to end testing of the system. Ideally before every change there should be an instance spun up with an appropriate database backend, a bunch of journals sent to the system via GRPC and the output checked.
This has been started in the /tests directory. Its passing right now but is essentially commented out
The text was updated successfully, but these errors were encountered: