Skip to content
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

Implementing basic integration testing using Enigo #97

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

BlackPhlox
Copy link

@BlackPhlox BlackPhlox commented Dec 29, 2020

First draft to implement unit test as referenced in issue #95.
Since now that dialoguer has gotten a CI setup, might be worth the effort.
In order to make integration testing for dialoguer, we have to use a cross-platform input simulation library, the only crate which is capable of this is Enigo. The initial draft has some caveats which are worth reviewing/addressing prior to any merging.

Caveats:

(Not relevant)

  • Having to extend the API in order to inject keypress simulation.
  • Having to check for initiation of the prompt to prevent an endless loop.
  • Having to use &mut self (prev &self) as the argument on interact (Already made this for input.rs from Allow FnMut for validate #96).
  • Linux Wayland is not supported by Enigo yet.
  • CI Build might fail on Linux if libxdo-dev is not installed (Library for simulating X11 keyboard/mouse input).

Result:

C:\...\dialoguer>cargo test
    Finished test [unoptimized + debuginfo] target(s) in 0.76s
     Running target\debug\deps\dialoguer-96ea80d1773ee7b6.exe

running 3 tests
test prompts::select::tests::test_ref_str ... ok
test prompts::select::tests::test_string ... ok
test prompts::select::tests::test_str ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target\debug\deps\select-46165e106123627c.exe

running 1 test
✔ Optionally pick your flavor · Vanilla Cupcake
test basic_navigation_produces_correct_selection ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests dialoguer

running 17 tests
test src\prompts\input.rs - prompts::input::Input::validate_with (line 128) ... ok
test src\prompts\input.rs - prompts::input::Input (line 32) ... ok
test src\prompts\confirm.rs - prompts::confirm::Confirm::with_theme (line 45) ... ok
test src\prompts\confirm.rs - prompts::confirm::Confirm (line 11) ... ok
test src\prompts\confirm.rs - prompts::confirm::Confirm::interact_on (line 128) ... ok
test src\prompts\multi_select.rs - prompts::multi_select::MultiSelect (line 10) ... ok
test src\prompts\input.rs - prompts::input::Input (line 18) ... ok
test src\edit.rs - edit::Editor (line 13) ... ok
test src\prompts\select.rs - prompts::select::Select (line 14) ... ok
test src\prompts\select.rs - prompts::select::Select::interact_on (line 206) ... ok
test src\prompts\password.rs - prompts::password::Password (line 12) ... ok
test src\prompts\select.rs - prompts::select::Select::interact_on_opt (line 229) ... ok
test src\prompts\select.rs - prompts::select::Select::with_prompt (line 162) ... ok
test src\prompts\select.rs - prompts::select::Select::item (line 115) ... ok
test src\prompts\select.rs - prompts::select::Select::items (line 135) ... ok
test src\prompts\select.rs - prompts::select::Select::with_theme (line 61) ... ok
test src\prompts\sort.rs - prompts::sort::Sort (line 12) ... ok

test result: ok. 17 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

Cargo.toml Show resolved Hide resolved
self.interact_on_opt(&Term::stderr())
}

pub fn set_before(&mut self, f: impl FnMut() + 'a) -> &mut Select<'a> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this fn?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be able to avoid it if I modify and create a custom Term. However, I can promise you it won't be pretty and goes against basic design principles. I agree that we should minimize any fn's that does not benefit the user. So it might be an idea to find an use-case for it?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please explain a bit on why exactly does enigo stuff need to happen after rendering the prompt and not before the whole interact fn?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't and I think it should be prior to any rendering. I just did it as a test for the sake of getting visual feedback.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, we don't need this function. Please setup enigo before calling interact in the test.

Copy link
Author

@BlackPhlox BlackPhlox Dec 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.
Next step is:

  • We have some test in bottom of prompts/select.rs, do we want that to stay or should it also be moved to tests/select.rs?
  • Configure CI so that the integration test passes

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are unit tests. We don't want to move them to tests folder.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, I've renamed the pr to integration test (based on this).
Regarding CI, we currently use cargo test --lib. We have to use cargo test --tests to also accommodate the integration tests. Seen as I don't have the rights to cancel a workflow, I would rather have you monitoring the workflow with the changes. As it previously created an infinite loop when calling the 'before' fn after the rendering step, but it might still do it (It only happens in the workflow).

Either way, this doesn't have to be rushed by any means, especially given the date, Happy New Year Pavan! 🎆

@BlackPhlox
Copy link
Author

BlackPhlox commented Dec 30, 2020

@pksunkara Even though it doesn't create an endless loop locally, it does on the CI, please cancel this workflow: https://github.com/mitsuhiko/dialoguer/actions/runs/452562230/workflow

@BlackPhlox BlackPhlox changed the title Implementing basic unittesting using Enigo Implementing basic integration testing using Enigo Dec 30, 2020
@pksunkara
Copy link
Collaborator

Happy new year to you too. Instead of me monitoring the workflow, you can try to get the CI working in a different branch after enabling github actions for your fork. I think that's a good way to test the CI before updating the PR.

@pksunkara
Copy link
Collaborator

Is this ready to be reviewed? I didn't get any notification from this PR after my last comment?

@BlackPhlox
Copy link
Author

Sorry, have been busy with work. It works locally. However, the integration test sticks in an endless loop when run via CI. I believe this is either a but or a limitation of console which dialoguer is built on top of. You can replicate this issue locally if you use a terminal that hooks into another terminal and runs the program, for example, IntelliJ's in-program terminal has the same issue. I might create an issue over at the console repo. Right now I don't the time nor do I have access to IntelliJ programs as my license has expired.

@pksunkara
Copy link
Collaborator

pksunkara commented Jan 27, 2021 via email

@BlackPhlox
Copy link
Author

Because current yaml does not include running the integration test when triggered. So technically you can merge this pr without issues, its just that if you change cargo test --lib to cargo test --tests in the yaml the CI will never end and just keep running indefinitely. Though local integration test is possible.

@bew
Copy link

bew commented Mar 15, 2021

Hello @BlackPhlox, I don't understand why you took a graphical input simulation lib for this..
dialoguer is (as far as I know) a terminal helper crate, it doesn't have anything to do with graphics like X11/Wayland nor does it has to deal with cross-platform input systems.

Terminal programs are pretty simple to test in general because the interface to interact with them is universally known and is based on stream of keys and other escape sequences.

To me enigo is the wrong tool for the job here, you don't need this, you don't need the complexity of GUI stuff to test a terminal tool.

To do this right @mitsuhiko, I think that the underlying crate console that is used should be initialized with a dummy/virtual terminal that you can interact with programatically for your tests (to send keys).

@pksunkara pksunkara added this to the 0.11.0 milestone Apr 11, 2023
@pksunkara pksunkara modified the milestones: 0.11.0, 0.12.0 Sep 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants