t.me/atinfo_chat Telegram группа по автоматизации тестирования

Как проверить окончание загрузки файла без Thread.Sleep?

Теги: #<Tag:0x00007f7488e4e838> #<Tag:0x00007f7488e4e748> #<Tag:0x00007f7488e4e608>

Как можно проверить что файл загрузился не используя Thread.Sleep?
Через проверку в файловой системе я так понимаю не получится сделать без слипов?
Вроде как-то можно сделать через проверку состояния js-события.
Как это можно реализовать на C#?

Проверив состояние js события, ты проверишь только то, как завершилось это самое js событие, что не означает, что файл загружен. Валидной проверкой будет всё же наличие файла в системе.
А чем тебя sleep в этом случае не устраивает? Просто сделай его более умным - проверяй наличие файла, скажем, каждые 500 миллисекунд на протяжении 15 секунд (цифры отфонарные).
И да, наверняка есть библиотека, которая будет ждать появления файла, но там будет тот же слип внутри :wink:

Попробуй вместо Thread.Sleep использовать Task.Delay
Тут, написано различие

А если файл большой, тогда нужно проверять что и размер не изменяется

Обычно, браузер создаёт темповый файл, когда скачивает, а по завершении удаляет его и остаётся только загруженный файл. Попробуй ждать именно своего файла, если знаешь его имя, или часть имени. Если не получится, то да, надо б ждать постоянства размера файла

Есть отличная библиотечка Awaitility для того чтобы красиво подождать какое то событие (будь то загрузка файла или ещё что то)

Прмерно так

await().atMost(30, SECONDS).untilAsserted(() -> assertThat(fileIsUploaded().isTrue());

На jave реализуется через создание кастомного ExpectedCondition, которое затем передается в WebDriverWait. В ExpectedCondition пишете функцию, в которой лучше всего чекать имя файла и то что его размер больше 0. На c# принцип такой же:

  1. Пишется своя функция ожидания
  2. В функции реализуется проверка по имени и размеру файла.
  3. Функция передается в webdriver.
  public static void WaitForFile(string filePath, int timeout)
    {
        var sw = Stopwatch.StartNew();
        while (sw.ElapsedMilliseconds <= timeout)
        {
            if (File.Exists(filePath))
                return;
            Thread.Sleep(TimeSpan.FromMilliseconds(500));
        }
        throw new TimeoutException($"Timeout {timeout} milliseconds exceeded while waiting for file '{filePath}' appearance.");
    }

как нибудь вот так

using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;

using System;
using System.IO;

String filename = "...";
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(wait_seconds));

wait.Until(o =>   {
// ignore WebDriver argument
bool FileExists = File.Exists(Filename);
// print some debugging info if needed
return FileExists;
}
); 


документация говорит
public bool OpenQA.Selenium.Support.UI.DefaultWait<OpenQA.Selenium.IWebDriver>.Until<TResult>(Func<IWebDriver, bool> condition);

// Summary: Repeatedly applies this instance’s input value to the given function until one of the following occurs:

• the function returns neither null nor false
• the function throws an exception that is not in the list of ignored exception types
• the timeout expires
Type parameter TResult: The delegate’s expected return type.
condition: A delegate taking an object of type T as its parameter, and returning a TResult.
Returns: The delegate’s return value.