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

During tests there may be deadlocks #1608

Closed
ofek opened this issue Jan 18, 2023 · 4 comments · Fixed by #1615
Closed

During tests there may be deadlocks #1608

ofek opened this issue Jan 18, 2023 · 4 comments · Fixed by #1615
Assignees
Labels
bug Something isn't working Task

Comments

@ofek
Copy link
Contributor

ofek commented Jan 18, 2023

What Operating System are you running on? Windows

In the following snippet if you uncomment the yielding of the Header the test will block:

from textual.app import App
from textual.screen import Screen
from textual.widgets import Footer, Header, Input


class MyScreen(Screen):
    def compose(self):
        # yield Header()
        yield Input()
        yield Footer()


class MyApp(App):
    def on_mount(self):
        self.install_screen(MyScreen(), 'myscreen')
        self.push_screen('myscreen')


async def test():
    app = MyApp()
    async with app.run_test():
        raise Exception('never raised')

        assert True
@Textualize Textualize deleted a comment from github-actions bot Jan 18, 2023
@ofek ofek changed the title During tests the Header widget may cause a deadlock During tests there may be deadlocks Jan 18, 2023
@ofek
Copy link
Contributor Author

ofek commented Jan 18, 2023

Another example:

from textual.app import App
from textual.containers import Container
from textual.screen import Screen
from textual.widget import Widget
from textual.widgets import Footer


class MyWidget(Widget):
    def compose(self):
        yield Footer()


class MyScreen(Screen):
    def compose(self):
        yield Container(MyWidget())


class MyApp(App):
    def on_mount(self):
        self.install_screen(MyScreen(), 'myscreen')
        self.push_screen('myscreen')


async def test():
    app = MyApp()
    async with app.run_test():
        raise Exception('never raised')

        assert True

@davep
Copy link
Contributor

davep commented Jan 18, 2023

Installed as a unit test in Textual, the most minimal version of this I can get to hang (although I can Ctrl+C it) is this:

from textual.app import App
from textual.screen import Screen
from textual.widget import Widget


class MyWidget(Widget):

    def compose(self):
        yield Widget()


class MyScreen(Screen):

    def compose(self):
        yield MyWidget()


class MyApp(App):

    def on_mount(self):
        self.install_screen(MyScreen(), 'myscreen')
        self.push_screen('myscreen')


async def test_this():
    app = MyApp()
    async with app.run_test():
        raise Exception('never raised')
        assert True

If I make MyApp.on_mount async and await the installation and the push of the screen:

from textual.app import App
from textual.screen import Screen
from textual.widget import Widget


class MyWidget(Widget):

    def compose(self):
        yield Widget()


class MyScreen(Screen):

    def compose(self):
        yield MyWidget()


class MyApp(App):

    async def on_mount(self):
        await self.install_screen(MyScreen(), 'myscreen')
        await self.push_screen('myscreen')


async def test_this():
    app = MyApp()
    async with app.run_test():
        raise Exception('never raised')
        assert True

it runs to completion just fine.

@davep
Copy link
Contributor

davep commented Jan 18, 2023

And, for the sake of completeness, just to be sure it's not some fluke and the screen isn't getting mounted but the pilot is ladning...

from textual.app import App
from textual.screen import Screen
from textual.widget import Widget


class MyWidget(Widget):

    def compose(self):
        yield Widget()


class MyScreen(Screen):

    def compose(self):
        yield MyWidget()


class MyApp(App):

    async def on_mount(self):
        await self.install_screen(MyScreen(), 'myscreen')
        await self.push_screen('myscreen')


async def test_this():
    app = MyApp()
    async with app.run_test() as pilot:
        assert pilot.app.screen is pilot.app.get_screen("myscreen")

That runs fine for me.

@davep davep added bug Something isn't working Task labels Jan 19, 2023
davep added a commit to davep/textual-sandbox that referenced this issue Jan 19, 2023
@github-actions
Copy link

Don't forget to star the repository!

Follow @textualizeio for Textual updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Task
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants