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

Rendering of headless tests fail #15447

Open
djalan opened this issue Apr 19, 2024 · 2 comments
Open

Rendering of headless tests fail #15447

djalan opened this issue Apr 19, 2024 · 2 comments

Comments

@djalan
Copy link

djalan commented Apr 19, 2024

Describe the bug

Hello

The synchronization of my headless tests fail once in a while and I woule like to know how I could improve my code. I am following what is in the documentation, basically calling the following after a mouse click:

 AvaloniaHeadlessPlatform.ForceRenderTimerTick();
 Dispatcher.UIThread.RunJobs();

I observed that this is not sufficient, therefore I created this function:

public static void SyncAvalonia(int numberTimes = 5)
{
    for (int i = 0; i < numberTimes; i++)
    {
        AvaloniaHeadlessPlatform.ForceRenderTimerTick(1_000_000);
        Dispatcher.UIThread.RunJobs();
    }
}

But unfortunately, this does not work perfectly because I will sometimes end up with a partially rendered window. I know this because I am taking screenshots after every click I perform during my test.

Over time, I changed the maximum number of iterations of the sync loop from 3 to 5. I guess it is because our application is becoming more and more complex and there are more things to be processed by the Dispatcher.

Is there a way where we could be 100% sure that all the Dispatcher jobs were run? The documentation of the method already says "run ALL jobs", but I still need my loop to calll RunJobs more than once.

Moreover, the 1_000_000 argument for ForceRenderTimerTick is the maximum that works. If I increase it to 10_000_000, my code will hang at this line.

As I am writing this, I am thinking that maybe if I introduce a await Task.Delay(100ms) in my loop it would give time for the Dispatcher to be fully populated instead of calling the next RunJobs too quickly.

To Reproduce

It is not happening very often. Once every week. I don't think I could reproduce this.

Expected behavior

Next window is fully rendered after clicking an element in my UI.

Avalonia version

11.0.9

OS

Windows

Additional context

I am using headless tests a bit differently than your documentation.

I am not acting on a ViewModel, but instead I am navigating from one screen to the other by clicking on different elements. I am using Headless to perform what is often known End-to-End testing or GUI tests.

@djalan djalan added the bug label Apr 19, 2024
@djalan djalan changed the title Headless tests rendering fails Rendering of headless tests fail Apr 19, 2024
@maxkatz6
Copy link
Member

@djalan you need to run Dispatcher jobs first, and only then timer tick. As otherwise render thread won't have anything to render.

But either way, we have tests for rendering into a bitmap:

var frame = window.CaptureRenderedFrame();

For this bug we definitely need a minimal repro, as it works for me.

Note, CaptureRenderedFrame used in our tests is just a handy extension on top of ForceRenderTimerTick:
https://github.com/AvaloniaUI/Avalonia/blob/master/src/Headless/Avalonia.Headless/HeadlessWindowExtensions.cs#L22-L24

@djalan
Copy link
Author

djalan commented Apr 26, 2024

@maxkatz6 I changed my code and most of the clicks in my application work well by simply using:

Dispatcher.UIThread.RunJobs();
AvaloniaHeadlessPlatform.ForceRenderTimerTick();

On the other hand, I experience problems when we use IPageTransition like in the below image. I tried using my loop to sync over 30 times with 10_000_000 ticks, but I still can't land on the final frame when I click the next button.

I had success in other parts of my application by calling my loop 4-5 times and with 100_000 or 1_000_000 ticks, but this one below looks like a dead end.

On two rare occassions, but it is not a constant behavior, I had success looping 20x with 10_000_000 ticks. I was able to see half of page 2, but it does not happen all the time. Increasing the numbers can end up yielding less frames.

PageTransition

I was able to sync (with a few loop calls) another part of the application that uses page transition too. I will compare the classes tomorrow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants