Подтвердить что ты не робот

Тестирование файлов перетаскивания на приложение

Я ищу способ выполнения перетаскивания файла/нескольких файлов в мое приложение из unit test. Например, выбрав некоторые файлы в Проводнике Windows, перетащите их и опустите в мое приложение.

Я могу проверить поведение перетаскивания между двумя компонентами в моем приложении (см. ниже - не стесняйтесь указывать, знаете ли вы, как лучше), но я понятия не имею, как сделать то же самое, когда данные из-за пределов моего приложения.

Я подумал об использовании отладчика для проверки "файла" Transferable, когда я выполняю операцию перетаскивания вручную, но должен быть лучший способ, чем жесткое кодирование полного Transferable.

Пример теста перетаскивания между компонентами

import org.junit.Test;

import javax.swing.Action;
import javax.swing.JTextField;
import javax.swing.TransferHandler;
import java.awt.event.ActionEvent;

import static org.junit.Assert.assertEquals;

public class DragAndDropTest {
  @Test
  public void dragAndDropBetweenTwoTextFields() {
    JTextField firstField = new JTextField();
    JTextField secondField = new JTextField();
    String testText = "Test text";
    firstField.setText( testText );
    firstField.selectAll();
    Action copyAction = TransferHandler.getCopyAction();
    copyAction.actionPerformed( new ActionEvent( firstField, ActionEvent.ACTION_PERFORMED, "Copy" ) );
    Action pasteAction = TransferHandler.getPasteAction();
    pasteAction.actionPerformed( new ActionEvent( secondField, ActionEvent.ACTION_PERFORMED, "Paste" ) );
    assertEquals( "Text is not copied", testText, secondField.getText() );
  }
}

Edit

Основываясь на комментариях по этому вопросу, я обновил свой фрагмент кода, чтобы "подделать" перетаскивание, предоставив жестко закодированный Transferable. Код также содержит небольшую основную программу, которая просто создает пустой фрейм, на котором вы можете отбрасывать файлы. Затем путь будет напечатан на консоли.

На моем ПК перетаскивание файла не использует javaFileListFlavor, а URI. Предыдущий опыт (см. этот вопрос) уже учил меня, что компонент Transferable, получаемый при перетаскивании чего-либо извне приложения Java, может отличаться тонким образом.

Итак, чтобы быть совершенно ясным: я хочу проверить часть моего кода, которая извлекает информацию из полученного Transferable. Код "обработка информации" (например, то, что происходит, когда приложение получает файл) может быть легко протестирован, не беспокоясь с D & D. Мне просто нужно убедиться, что я извлекаю правильную информацию из Transferable, и глупо тестировать это с помощью жестко закодированного Transferable.

import org.junit.Test;

import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.TransferHandler;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.util.List;

import static org.junit.Assert.assertEquals;

public class DragAndDropTest {
  private static DataFlavor URI_LIST_FLAVOR = null;
  static {
    try {
      URI_LIST_FLAVOR = new DataFlavor( "text/uri-list;class=java.lang.String" );
    }
    catch ( ClassNotFoundException ignore ) {
    }
  }

  @Test
  public void testFileDragAndDrop() throws IOException, UnsupportedFlavorException {
    JComponent testComponent = new JPanel();
    TestingTransferHandler transferHandler = new TestingTransferHandler();
    testComponent.setTransferHandler( transferHandler );
    Clipboard clipBoard = new JLabel(  ).getToolkit().getSystemClipboard();
    Transferable transferable = new Transferable() {
      @Override
      public DataFlavor[] getTransferDataFlavors() {
        return new DataFlavor[]{URI_LIST_FLAVOR};
      }

      @Override
      public boolean isDataFlavorSupported( DataFlavor flavor ) {
        return flavor == URI_LIST_FLAVOR;
      }

      @Override
      public Object getTransferData( DataFlavor flavor ) throws UnsupportedFlavorException, IOException {
        if ( flavor == URI_LIST_FLAVOR ) {
          return new String( "file:///home/robins/Desktop/swingx-1.0-javadoc.jar" );
        }
        throw new UnsupportedFlavorException( flavor );
      }
    };
    clipBoard.setContents( transferable, null );
    Action pasteAction = TransferHandler.getPasteAction();
    pasteAction.actionPerformed( new ActionEvent( testComponent, ActionEvent.ACTION_PERFORMED, "Paste" ) );
    assertEquals( transferable.getTransferData( URI_LIST_FLAVOR ), transferHandler.transferable.getTransferData( URI_LIST_FLAVOR ) );
  }

  private static class TestingTransferHandler extends TransferHandler{
    public Transferable transferable;
    @Override
    public boolean canImport( TransferSupport support ) {
      return true;
    }
    @Override
    public boolean importData( TransferSupport support ) {
      transferable = support.getTransferable();
      try{
        if ( transferable.isDataFlavorSupported( DataFlavor.javaFileListFlavor ) ) {
          System.out.println("File list flavor");
          List<File> fileList = ( List<File> ) transferable.getTransferData( DataFlavor.javaFileListFlavor );
          System.out.println( "fileList = " + fileList );
        }
        if ( transferable.isDataFlavorSupported( URI_LIST_FLAVOR )){
          System.out.println("URI list flavor");
          String uriList = ( String ) transferable.getTransferData( URI_LIST_FLAVOR );
          System.out.println( "uriList = " + uriList );
        }
        return true;
      } catch ( UnsupportedFlavorException e ) {
        return false;
      } catch ( IOException e ) {
        return false;
      }
    }
  }

  public static void main( String[] args ) {
    EventQueue.invokeLater( new Runnable() {
      @Override
      public void run() {
        JFrame frame = new JFrame( "TestFrame" );
        JPanel contentPane = new JPanel( new BorderLayout(  ) );
        contentPane.setTransferHandler( new TestingTransferHandler() );
        frame.setContentPane( contentPane );
        frame.setSize( 200,200 );
        frame.setVisible( true );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
      }
    } );
  }
}
4b9b3361

Ответ 1

Unit-testing Swing GUI всегда болезнен, не говоря уже о D & D. Однако я считаю, что это можно сделать.

Можно заметить две вещи:

  • В настоящее время вы вообще не тестируете D & D, а скорее копируете-вставляете. Это также форма передачи данных, но использование copyAction и pasteAction заставляет вас действительно не проходить ни один из шагов D & D

  • Вы упомянули, что хотите проверить часть, которая получает файл, и, следовательно, вы создали персонализированную Transferable, но я хотел бы утверждать, что вы пытаетесь проверить неправильную вещь. Часть, которая обрабатывает данные, может быть реализована как закрытый частный метод обработки Transferable, содержащий данные, и протестирована с помощью простого unit test (не задействованы компоненты Swing)

Я считаю, что то, что вы должны тестировать, если вы беспокоитесь о различиях D & D между разными ОС, заключается в том, что сам процесс D & D работает, то есть:

  • Компонент с данными (DragSource) запрашивается для предоставления данных и обеспечивает его
  • Компонент, запрашивающий данные (DropTarget), получает данные и обрабатывает их
  • Необязательно, вы можете проверить, разрешены или запрещены разные условия (например, копия или перемещение и т.д.).

Вы можете проверить это, используя класс FEST ComponentDragAndDrop (см. здесь).

Если вы хотите написать свою собственную реализацию (зачем вы хотите это сделать?!), вы можете:
Замените как исходный, так и целевой компоненты TransferHandler с помощью mocks (или шпионов, чтобы быть более точным), что помимо вызова реальных методов позволит вам проверить, что ожидаемые методы вызывают с ожидаемыми данными

Ответ 2

если вы не ограничены модульным тестированием, попробуйте написать тест GUI. Для Swing существует несколько фреймворков, посмотрите эту ветку - Структурная схема тестирования для пользовательского интерфейса Swing

Я использовал jemmy некоторое время назад, и все было в порядке, если тест был прост

Ответ 3

Возможно, AutoIt Script может помочь: См. здесь

Вы можете создать окно Script, чтобы имитировать необходимые события мыши или клавиши. Затем запустите этот Script из вашего теста и посмотрите, что произойдет.

Надеюсь, что это поможет.

Ответ 4

Вы видели класс Robot. Это довольно круто для тестирования взаимодействия человека. Я не знаю, можно ли перетаскивать файлы.. но это имеет смысл, что вы можете!

Ответ 5

Вы можете использовать Swinput для имитации событий ввода в Linux.

Ответ 6

Попробуйте использовать mocks. Я использую Mockito framework.