-
Notifications
You must be signed in to change notification settings - Fork 94
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
tests: integration test battery #3654
Conversation
46c84cc
to
0e41d68
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Three tests didn't port well from the unit test framework and have errors which need cleaning up, any ideas?
) | ||
|
||
|
||
@pytest.mark.skip('TODO: the delta doesnt seem to have an id for some reason') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The delta seems to be missing the id field.
@pytest.mark.skip( | ||
reason='TODO: trigger_tasks is resultin in traceback due to ' | ||
'missing task_globs arg') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Failing due to an argument error in the server?
assert len(update_tasks) == len(collect_states(data, TASK_PROXIES)) | ||
|
||
|
||
@pytest.mark.skip('TODO: fix this test') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The update doesn't do anything because the workflow hasn't changed state, how do I trick it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think 95% of the changes in this pull request are files being moved.
Probably %2 are the scheduler/cli changes, that I will leave to others with more experience there to review/comment.
The rest are test related, and it looks great.
In Java, normally we would have unit & functional tests. Mocked and even things like the pytest fixtures exist in JUnit/TestNG too, but they are used in both unit & functional tests. Functional tests would be for things related to stories/requirements for features of the system (e.g. we send a JMS message to a queue for every new blog post), and integration for things that required external modules/systems (e.g. the system is able to send a JMS message to ActiveMQ version 1.2.3).
In JS it depends on the framework, but nowadays people are converging towards unit without a DOM, or with a mocked DOM, and end-to-end with cypress/selenium/nightwatch, meaning that it has a browser with a valid DOM. I think I haven't seen integrations tests in JS yet, only unit/functional/e2e/and acceptance testing, all but unit very similar.
For a Ruby developer, I think they have some sort of tests for model classes that are unit. Then they have specs that may be functional tests, and Capybara which they say is for acceptance, which looks like functional or e2e tests too 😕
So the idea of a functional and unit test is clear for me. The idea of functional and integration is a bit blur, unless I really understand both the system under test and the test harness & tools, as that may differ in a different project (even though there are definitions on Wikipedia, books, etc).
After these changes in Cylc, I think I will write unit tests for any small changes, that can be done without a running workflow or with minimum mocking.
If I require mocking complex objects, or have parts of the system working/running, I will probably need an integration test, using the fixtures in the integration module.
And I would write a functional test if I introduced something new in Cylc that I would like to make sure it works as a whole (even if I have parts of the new feature being tested with unit tests, maybe I could still want to have a complete end to end test of all the parts of the system?).
Is that close to the right use of the new different tests @oliver-sanders for Cylc?
Cheers
Bruno
p.s.: ISTQB has a glossary for testing, it used to be popular some 10 years ago, there are probably over 20 different types of testing 👀
tests/integration/__init__.py
Outdated
SchedulerStop(StopMode.AUTO.value) | ||
) | ||
except asyncio.TimeoutError: | ||
# but be prepared to use the nuclear option |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😄
@pytest.fixture(scope='session') | ||
def port_range(): | ||
ports = glbl_cfg().get(['suite servers', 'run ports']) | ||
return min(ports), max(ports) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
sys.exit(1) | ||
self.close_logs() | ||
* Initialise the network components. | ||
* Initialise mangers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/mangers/managers
It is free software, you are welcome to | ||
redistribute it under certain conditions; | ||
see `COPYING' in the Cylc source distribution. | ||
""" % CYLC_VERSION |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this was in the scheduler before? It makes sense to keep it here IMO 👍
@@ -77,6 +84,7 @@ | |||
"overrides the suite definition.") | |||
|
|||
|
|||
@lru_cache() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sonds like a good idea!
|
||
The Scheduler itself should be a Python object you can import and | ||
run in a regular Python session so cannot contain this kind of | ||
functionality. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 ! The code of the Scheduler
class/object looks way better. I can't comment further as I am not that familiar, so will leave to others (especially @hjoliver ) to review that. And it got some types added to the class attributes 🎉 thanks!
raise exc2 from None | ||
ret = 2 | ||
except Exception: | ||
ret = 3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was going to ask why not throw/return the exception. But then realized this is the code to be used in exit()
function. Maybe add a comment in the function stating that the returned value is an int, and that it's used to provide the command execution status/exit code?
Yes, the distinction is subtle and I think in truth it's really more of a scale between unit and functional rather than a distinct clustering. I've put the framework for running suites within the integration battery to help "draw a line in the sand".
Yep, that's what I was thinking, bang on! My thinking is:
But I'm no testing expert! Input greatly appreciated. |
Someone wrote a helpful article for us 😁 https://www.softwaretestinghelp.com/the-difference-between-unit-integration-and-functional-testing/ |
:+1 we have at least a clear definition for Cylc of what is what, and where each test should go. I can't promise I will get it right when I have to choose between the three types, but I feel confident that reading the docs and looking at existing tests I should find the right test, and eventually that will become natural 🤞
Yup! I had seen this one too. And each directory has the helpful |
Yep, I think I used the diagram from that article in my proposal. I did a bit of reading which was quite confidence giving seeing people confirm what I've been slowly realising. The really big bit is time to write and time to debug. We spend so much time on functional tests, I personally sunk nearly an entire week into them (less than the time it took to write this new framework) just to fix broken tests. Hopefully this will help accelerate future development, might take a while to get there though... |
0e41d68
to
6c79c30
Compare
Rebased and deconflicted, test changes ported from #3500. |
* move cli stuff into the cli * move functional stuff out of the cli * add an interface for creating scheduler options objects * tidy the --format argument * move daemonise logic to scheudler_cli * move event loop logic to scheduler_cli * move logging into scheduler_cli * move start message to scheduler_cli * store id as top-level attr
|
@datamel and @kinow thank you for stepping in to review. There are a couple of specific aspects which could do with standalone reviewing:
|
--ignore=cylc/flow/data_messages_pb2.py | ||
testpaths = | ||
cylc/flow/ | ||
tests/lib/python/ | ||
tests/unit/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tests/unit/ | |
tests/unit/ | |
tests/integration/ |
Adding this path enables integration tests to be picked up correctly by visual studio code for easy debugging. I'm happy for this change not to go in (as it relates to my debugging process) but may help others too. Without it I'm not 100% sure why pytest was picking up the integration tests...hmmm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I purposefully left the integration tests out of testpaths
so that when you run pytest
it defaults to running tests/unit
. If there's another way to define the default test set I'm game
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, no worries :)
The last commit should fix the hanging functional test. Hopefully this is the last time I have to mess with asyncio in this PR! Even though it's only a few lines getting the asyncio code right has been a lot of work, the integration test framework only took one day. Here are some lessons learned:
|
….merge.scheduler_key_tidy.1
Merged and de-conflicted (tried rebase, it was horrible). |
Fixed |
That sounds like some stuff that I don't want to rediscover the hard way in the future. Would it be worth copying to code comments for reference (in |
Yep, will do. |
Deconflicted. |
@@ -122,7 +124,8 @@ def __str__(self): | |||
return self.value | |||
|
|||
|
|||
class Scheduler(object): | |||
@dataclass | |||
class Scheduler: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Impressive/massive job 👍 I scanned almost everything; tests work; I like the new integration test framework; my two comments above aren't important so I'll merge this and we can get on with the horrifying conflict resolution ...
@hjoliver best make sure you're happy with the scheduler / scheduler_cli re-alignment and the general gist of the change.
I'm happy with it - one question above indicates I don't fully understand your use of asyncio yet ... but it works fine, and it I guess it doesn't matter if some asyncio tasks are still entirely blocking.
- @dwsutherland if you could cast your eye over the asyncio stuff in scheduler/scheduler_cli.
- @dwsutherland best make sure I've not butchered the tests.
David is on leave for a week and I think he can come back to this post merge. The first bullet point (scheduler/_cli) seems simple enough (my question above notwithstanding) and the second is "just tests".
Implementation of the proposal #3616
Closes #3547
TODO:
Highlights:
~/cylc-run
.cylc/flow/scheduler*.py
.tests/
.Usage:
To run all tests:
One day this will be simplified further to:
Philosophy
There is some kind of scale with testing approaches: unit < integration < functional.
When debugging start with the unittests and move up once you've fixed them all. The integration tests don't stand a chance of passing if the unittest are broken, the functional tests don't stand a chance of passing if the integration tests are broken.
Keep the test types separate, use the right tool for the job.
I've put README.md files in each of the test directories, take a look and see what you think, I'm not a testing expert - edits welcome!
Integration Tests:
Documentation:
tests/i/README.md
tests/i/test_examples.py
Implementation:
Parallelism:
pytest.asyncio
async
test functions.pytest.asyncio
is not for parallelising tests (see GH issues).pytest-xdist
for parallelism:Scheduler:
Scheduler
class in Python.sys.exit
, logging) has been moved toscheduler_cli
.Caveats:
Test teardown fails on NFS.Error suppressed until resolution of public database not closed correctly - consider persisting the connection #3666cylc run
is not displayed in colour afterdaemonize()
.I've had to [temporally] skip the client connection tests due to an asyncio event loop incompatibility.Fixed.The scheduler exits withos._exit
rather thansys.exit
, this is not ideal.There pytest waits for approx 10s after running integration tests, asyncio shutdown issue?Requirements check-list:
CONTRIBUTING.md
and added my name as a Code Contributor.