Как JUnit находит тестируемый подключаемый модуль eclipse?

Я пишу подключаемый модуль (ClassRefactoringPlugin), который проверяет исходный код в Eclipse 3.6.1. Подключаемый модуль содержит класс CallData, который проверяет исходный файл Java и определяет, какие элементы Java вызываются из метода с помощью операций JDT. Я написал тест JUnit 4 для этого класса, который также находится в проекте ClassRefactoringPlugin. Когда я запустил его как тест подключаемого модуля JUnit, я получил:

Java Model Exception: Java Model Status [ClassRefactoringPlugin does not exist]

Что я сделал не так? Конфигурация указывает на запуск со всей рабочей областью и включенными целевыми подключаемыми модулями, а ClassRefactoringPlugin находится в моем каталоге dropins. (Хотя разве версия плагина проекта не должна распознаваться порожденной рабочей областью?)

Вот трассировка стека:

!MESSAGE CallData.calculateCalledMethods: Java Model Exception: Java Model Status [ClassRefactoringPlugin does not exist]
Java Model Exception: Java Model Status [ClassRefactoringPlugin does not exist]
        at org.eclipse.jdt.internal.core.JavaElement.newJavaModelException(JavaElement.java:502)
        at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:246)
        at org.eclipse.jdt.internal.core.Openable.openAncestors(Openable.java:504)
        at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:240)
        at org.eclipse.jdt.internal.core.Openable.openAncestors(Openable.java:504)
        at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:240)
        at org.eclipse.jdt.internal.core.Openable.openAncestors(Openable.java:504)
        at org.eclipse.jdt.internal.core.CompilationUnit.openAncestors(CompilationUnit.java:1170)
        at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:240)
        at org.eclipse.jdt.internal.core.SourceRefElement.generateInfos(SourceRefElement.java:107)
        at org.eclipse.jdt.internal.core.JavaElement.openWhenClosed(JavaElement.java:515)
        at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:252)
        at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:238)
        at org.eclipse.jdt.internal.core.JavaElement.getChildren(JavaElement.java:193)
        at org.eclipse.jdt.internal.core.JavaElement.getChildrenOfType(JavaElement.java:207)
        at org.eclipse.jdt.internal.core.SourceType.getMethods(SourceType.java:403)
        at nz.ac.vuw.ecs.kcassell.utils.EclipseSearchUtils.addDesiredMethods(EclipseSearchUtils.java:333)
        at nz.ac.vuw.ecs.kcassell.utils.EclipseSearchUtils.getMethods(EclipseSearchUtils.java:210)
        at nz.ac.vuw.ecs.kcassell.callgraph.CallData.collectMethodCallData(CallData.java:203)
        at nz.ac.vuw.ecs.kcassell.callgraph.CallData.calculateCalledMethods(CallData.java:176)
        at nz.ac.vuw.ecs.kcassell.callgraph.CallData.collectCallData(CallData.java:151)
        at nz.ac.vuw.ecs.kcassell.callgraph.CallDataTest.testCollectCallData(CallDataTest.java:67)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at junit.framework.TestCase.runTest(TestCase.java:168)
        at junit.framework.TestCase.runBare(TestCase.java:134)
        at junit.framework.TestResult$1.protect(TestResult.java:110)
        at junit.framework.TestResult.runProtected(TestResult.java:128)
        at junit.framework.TestResult.run(TestResult.java:113)
        at junit.framework.TestCase.run(TestCase.java:124)
        at junit.framework.TestSuite.runTest(TestSuite.java:232)
        at junit.framework.TestSuite.run(TestSuite.java:227)
        at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
        at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
        at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
        at org.eclipse.pde.internal.junit.runtime.RemotePluginTestRunner.main(RemotePluginTestRunner.java:62)
        at org.eclipse.pde.internal.junit.runtime.UITestApplication$1.run(UITestApplication.java:116)
        at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
        at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:134)
        at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3515)
        at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3164)
        at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2640)
        at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604)
        at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2438)
        at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:671)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
        at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:664)
        at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
        at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115)
        at org.eclipse.pde.internal.junit.runtime.UITestApplication.start(UITestApplication.java:47)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:619)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1407)
        at org.eclipse.equinox.launcher.Main.main(Main.java:1383)

Мне интересно, может ли сообщение об ошибке быть отвлекающим маневром. Ошибка возникает при вызове IMethod[] methods = type.getMethods();

Если я установлю там точку останова и посмотрю на type в представлении Variables отладчика, я увижу:

CallDataTest (not open) [in CallDataTest.java [in nz.ac.vuw.ecs.kcassell.callgraph [in test [in ClassRefactoringPlugin]]]]

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

public static void activateWorkbench() {
    // possible for PlatformUI.getWorkbench to throw an IllegalStateException
    // if the workbench is not yet started e.g createAndRunWorkbench() has not yet been called
    IWorkbench workbench = PlatformUI.getWorkbench();
    IWorkbenchWindow workbenchWindow =
        workbench.getActiveWorkbenchWindow();
    workbenchWindow.getActivePage();
}

Затем я пытаюсь получить тип, используя его дескриптор:

protected IType iType = EclipseUtils.getTypeFromHandle(
        "=ClassRefactoringPlugin/test<nz.ac.vuw.ecs.kcassell.callgraph{CallDataTest.java[CallDataTest");

public static IType getTypeFromHandle(String handle) {
IType type = null;
IJavaElement element = JavaCore.create(handle);
if (element == null) {
    System.err.println("  No element created from " + handle);
} else if (element instanceof IType) {
    type = (IType) element;
}
    return type;
}

Я новичок в разработке плагинов, поэтому буду признателен за любую помощь.

Привет, Кит


person kc2001    schedule 29.07.2010    source источник
comment
Я подтверждаю, что вам не нужно помещать экспортированный плагин в папку dropins, потому что Eclipse использует версию проекта плагина, который вы пишете, при запуске конфигурации JUnit Launch. Можете ли вы вставить полную трассировку стека, потому что я не думаю, что проблема связана с конфигурацией запуска Junit. Если вы можете запустить его, я думаю, тестовый класс доступен на главной вкладке конфигурации Junit Run?   -  person Manuel Selva    schedule 29.07.2010
comment
Я не совсем уверен, что вы подразумеваете под основной вкладкой конфигурации Junit Run? В Eclipse, если я делаю Run->Run Configurations, я получаю окно Run Configurations, в котором CallDataTest указан как тест подключаемого модуля JUnit. Это то, что вы хотели знать? Я редактирую исходный пост, чтобы включить трассировку стека.   -  person kc2001    schedule 30.07.2010
comment
Я обновил информацию в основном посте, чтобы отразить переход на более новую версию Eclipse.   -  person kc2001    schedule 14.04.2011
comment
Здравствуйте кс2001. Вы предложили награду и проголосовали за мой ответ на тот же вопрос, что и решение вашего. Пожалуйста, отметьте мой вопрос как принятый ответ. Было бы жалко выбрасывать эти очки впустую. Спасибо.   -  person sprite    schedule 17.04.2011


Ответы (2)


Я немного не уверен, что именно вы пытаетесь здесь сделать, но похоже, что вы пытаетесь написать тест JUnit для своего плагина. Это правильно?

В соответствии с идентификатором дескриптора элемента java, который вы создаете, в вашей рабочей области должен быть проект с именем ClassRefactoringPlugin, а также исходная папка с именем test и класс java с именем CallDataTest в пакете с именем nz.ac.vuw.ecs.kcassell.callgraph.

Я предполагаю, что это не так и что вы хотите сослаться на файл класса в плагине, который вы только что создали.

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

Я могу неправильно понять, что вы пытаетесь сделать, но похоже, что вы пытаетесь получить доступ к java-файлу, которого нет в вашей рабочей области. Если вы можете подтвердить, что это то, что вы хотите сделать, я могу указать вам на некоторый тестовый код, который делает именно то, что вы хотите.


Есть несколько проектов с открытым исходным кодом, которые делают именно это, и вы можете позаимствовать часть их исходного кода для своих целей. Я знаком с проектом Groovy-Eclipse http://groovy.codehaus.org/Eclipse+Plugin (поскольку я руковожу этим проектом).

Вот ссылка на класс, который мы используем для создания и управления тестовыми проектами:

https://svn.codehaus.org/groovy/eclipse/trunk/ide-test/org.codehaus.groovy.eclipse.tests/src/org/codehaus/groovy/eclipse/test/TestProject.java

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

person Andrew Eisenberg    schedule 19.04.2011
comment
Я считаю, что все предпосылки, о которых вы упомянули, установлены правильно. Я не понимаю, вы ссылаетесь на тестовую рабочую область. У меня есть рабочая область, содержащая мой ClassRefactoringPlugin, в которой есть папки src и test. Когда я щелкаю правой кнопкой мыши CallDataTest и запускаю тест плагина JUnit, создается новое рабочее место. Если я сделаю это в режиме отладки, я смогу выполнить код в тесте с помощью отладчика. Вот почему мне интересно, может ли сообщение об ошибке вводить в заблуждение. Кстати, код моего плагина отлично работает в порожденной рабочей области, когда я его отлаживаю, но не когда я пытаюсь запустить тесты JUnit. - person kc2001; 19.04.2011
comment
Правильно. Тесты подключаемых модулей JUnit порождают новую рабочую область, но эта рабочая область изначально пуста. Вы пытаетесь получить доступ к проекту (и его исходному коду), который существует в обычной рабочей области, но не в рабочей области JUnit среды выполнения. Я предполагаю, что когда вы запускаете рабочую область среды выполнения (не среды выполнения JUnit), у вас есть проект в этой рабочей области с именем CallDataTest. Вам нужно импортировать CallDataTest в рабочее пространство JUnit, если вы хотите создать на его основе IJavaElement. Для этого нет простого API, но есть много проектов с открытым исходным кодом, которым нужно делать то же самое. - person Andrew Eisenberg; 19.04.2011
comment
Обновлен мой ответ, чтобы включить ссылку на пример исходного кода. - person Andrew Eisenberg; 19.04.2011
comment
Я думаю, что моя главная проблема заключалась в том, что мне не удалось настроить проект в junit-workspace. Хотя у меня это еще не работает, я чувствую, что вашей помощи должно быть достаточно, чтобы получить его. Если в ближайшее время не придет супер ответ, вы получите награду. Ваше здоровье! - person kc2001; 20.04.2011
comment
Это непростая вещь. :) И нам потребовалось много времени, чтобы это исправить. Так что, не стесняйтесь возвращаться, если у вас есть еще вопросы. - person Andrew Eisenberg; 20.04.2011

Была похожая ошибка по разным причинам. Моя ошибка началась после переименования целевого пакета в проекте. После того, как я безуспешно попробовал решение от paskster, я начал копать.

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

Это принятый ответ на другой вопрос: Исключение модели Java: статус модели Java [gen [in MyApp] не существует] после очистки проекта Android Eclipse

Поскольку владелец этого вопроса проголосовал за этот ответ как за решение со ссылкой на этот вопрос, я решил опубликовать его и здесь.

person sprite    schedule 17.04.2011
comment
К сожалению, моя первоначальная радость от прочтения вашего поста была преждевременной. Я сделал каждое имя согласованным, о котором я мог думать, и все еще имел проблему. Тем не менее, я не заметил какой-либо конкретной тестовой информации в MANIFEST. - person kc2001; 19.04.2011