MoreUnit / MoreUnit-Eclipse

MoreUnit is an Eclipse plugin that should assist you in writing more unit tests. It supports all programming languages (switching between tests and classes under tests...) and has specific support for Java (creating test stubs, mock support, decoration, refactoring support...).
https://moreunit.github.io/MoreUnit-Eclipse/
58 stars 26 forks source link

jump to test/source works fine from Test to CUT, but reverse prompts to create test class #141

Closed davidmichaelkarr closed 11 months ago

davidmichaelkarr commented 2 years ago

I'm using Eclipse 2021-12. I've been using MoreUnit for quite a while and it's worked perfectly fine.

Today I had to look at a service that I haven't looked at before, but it's in a large suite of other applications we maintain. It will have many similarities to the other services I've worked on with it.

I'm now seeing an odd behavior with "jump to test/source", but not in all services. In the little testing I've done so far, if it works fine for one class in a service, it works fine for all of them, and similarly, if it doesn't work for one class in a service, it shows the same problem for all of them.

If I'm sitting in a test class and execute "jump to test/source" (bound to ctrl-j), it correctly jumps to the CUT (code under test), which you might call "source".

However, when I press ctrl-j in the CUT, it presents the dialog to create a new test class. I've verified this with multiple classes in the service, and I've verified that I have the normal "src/test/java" and "src/main/java" setup, and that both CUT and test class are in the same package.

What else does MoreUnit look at to determine whether a test class already exists for the CUT?

dstango commented 2 years ago

Check the "rule for naming test files" in MoreUnit-Preferences. If the names of the existing test classes don't match that pattern, MoreUnit cannot find them from the CUT. The other way round MoreUnit seems to analyze the opened test source file and follow the references to the CUT.

davidmichaelkarr commented 2 years ago

I never change that from the default. However, I also see a small, perhaps understandable, difference between the workspace preferences and the project properties, and the test cases where this is not behaving match that pattern.

The CUT is called "ApplicationUtils", and the test class is called "ApplicationUtilsTest".

This is from workspace preferences: image

This is from project properties: image

The project is configured to allow Groovy (even though Groovy source files are present), so that difference is understandable.

dstango commented 2 years ago

What happens if you actually follow the dialog to create a new test class. It should create a new test class right next to the existing one. I had it that there was a tiny little typo in the naming, that didn't jump into my eyes at first (e.g. ApplicationUtils and ApplicationUtlisTest) -- when I generated the proposed test class it became quite apparent ... I'm just guessing, but that's what I would try out.

davidmichaelkarr commented 2 years ago

I understand the part about following through with the dialog, but I'm not sure what you're saying about "Utlis". There is no discrepancy here.

So when I went and looked at the dialog again to try to let it finish, I realized that it's not letting me finish it. The "Next" and "Finish" buttons are greyed out, and there is no error message. That makes it seem like it thinks the class already exists.

image

davidmichaelkarr commented 2 years ago

And, I just tried walking back through releases. I always keep the last 2-3 releases installed for comparisons. I have the same git repos in each one. I verified I see the same behavior in 2021-09, but in 2021-06, it's not happening. I tested the same scenario with the exact same class. In "ApplicationUtils.java", pressing Ctrl-j just goes to "ApplicationUtilsTest.java". The latter has MoreUnit 3.3.0, the former(s) 3.3.1.

davidmichaelkarr commented 2 years ago

And note that I also tried to simply add a character in the generated class name in that dialog, and that instantly made the Next and Finish buttons sensitive. It appears that there are two blocks of logic that determine whether the corresponding test class exists, the first one that has the logic of whether to present the "Create Class" dialog, and the second in the logic in that dialog. The second block is working correctly, but the first one is not.

dstango commented 2 years ago

Looks like you've very much tried everything to pinpoint it down, so it's probably a bug...

davidmichaelkarr commented 2 years ago

It might go without saying, but if you're unable to repeat it on your side, I'd be willing to install test versions you produce to narrow down the RC.

dstango commented 2 years ago

I'm not part of the developers of this plugin -- just a user like you, throwing in some ideas ;-) ... Anyhow: providing a minimal project that reproduces the issue might be helpful for the developers.

davidmichaelkarr commented 2 years ago

Ok, well, I can confirm that a simple test case in a "hello world" project from spring.io does NOT demonstrate it. I don't know what ingredient is causing it get confused.

davidmichaelkarr commented 2 years ago

I should have looked in the log earlier.

In my current test case with ApplicationUtils.java, when I press Ctrl-j anywhere in the class, it just prints this:

!ENTRY org.moreunit 1 0 2022-02-03 15:09:13.383
!MESSAGE No method found surrounding cursor position.

I tried it many different locations in the source file, including within methods.

However, I also noticed earlier in the log file multiple occurrences of this:

!ENTRY org.moreunit.core 2 0 2022-02-03 15:03:56.388
!MESSAGE Error calling extension: org.moreunit.handler.Jumper.jump()
!STACK 0
java.lang.NullPointerException: Cannot invoke "org.eclipse.swt.widgets.Button.getSelection()" because "this.spockToggle" is null
    at org.moreunit.wizards.MoreUnitWizardPageOne.getCompilationUnitName(MoreUnitWizardPageOne.java:1329)
    at org.eclipse.jdt.ui.wizards.NewTypeWizardPage.getUniqueJavaTypeName(NewTypeWizardPage.java:798)
    at org.eclipse.jdt.ui.wizards.NewTypeWizardPage.initTypePage(NewTypeWizardPage.java:752)
    at org.moreunit.wizards.MoreUnitWizardPageOne.init(MoreUnitWizardPageOne.java:204)
    at org.moreunit.wizards.NewTestCaseWizard.addPages(NewTestCaseWizard.java:57)
    at org.eclipse.jface.wizard.WizardDialog.createContents(WizardDialog.java:632)
    at org.eclipse.jface.window.Window.create(Window.java:431)
    at org.eclipse.jface.dialogs.Dialog.create(Dialog.java:1094)
    at org.eclipse.jface.window.Window.open(Window.java:788)
    at org.moreunit.wizards.NewClassyWizard.open(NewClassyWizard.java:40)
    at org.moreunit.elements.TypeFacade$OpenNewClassWizard.getCorrespondingMember(TypeFacade.java:320)
    at org.moreunit.elements.TypeFacade.getOneCorrespondingMember(TypeFacade.java:130)
    at org.moreunit.handler.JumpActionExecutor.executeJumpAction(JumpActionExecutor.java:106)
    at org.moreunit.handler.JumpActionExecutor.executeJumpAction(JumpActionExecutor.java:80)
    at org.moreunit.handler.Jumper.jump(Jumper.java:14)
    at org.moreunit.core.extension.JumperExtensionManager$1.run(JumperExtensionManager.java:38)
    at org.moreunit.core.extension.JumperExtensionManager$1.run(JumperExtensionManager.java:1)
    at org.moreunit.core.util.ExtendedSafeRunner$GenericRunnable.doRun(ExtendedSafeRunner.java:21)
    at org.moreunit.core.util.ExtendedSafeRunner$SafeRunnable.run(ExtendedSafeRunner.java:64)
    at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
    at org.moreunit.core.util.ExtendedSafeRunner.run(ExtendedSafeRunner.java:43)
    at org.moreunit.core.util.ExtendedSafeRunner.applyTo(ExtendedSafeRunner.java:27)
    at org.moreunit.core.extension.JumperExtensionManager.jump(JumperExtensionManager.java:26)
    at org.moreunit.core.commands.JumpActionExecutor.execute(JumpActionExecutor.java:33)
    at org.moreunit.core.commands.JumpActionExecutor.execute(JumpActionExecutor.java:22)
    at org.moreunit.core.commands.JumpActionHandler.execute(JumpActionHandler.java:16)
    at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:283)
    at org.eclipse.ui.internal.handlers.E4HandlerProxy.execute(E4HandlerProxy.java:97)
    at jdk.internal.reflect.GeneratedMethodAccessor142.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
    at org.eclipse.e4.core.internal.di.InjectorImpl.invokeUsingClass(InjectorImpl.java:317)
    at org.eclipse.e4.core.internal.di.InjectorImpl.invoke(InjectorImpl.java:251)
    at org.eclipse.e4.core.contexts.ContextInjectionFactory.invoke(ContextInjectionFactory.java:173)
    at org.eclipse.e4.core.commands.internal.HandlerServiceHandler.execute(HandlerServiceHandler.java:156)
    at org.eclipse.core.commands.Command.executeWithChecks(Command.java:488)
    at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:487)
    at org.eclipse.e4.core.commands.internal.HandlerServiceImpl.executeHandler(HandlerServiceImpl.java:213)
    at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.executeCommand(KeyBindingDispatcher.java:308)
    at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.press(KeyBindingDispatcher.java:580)
    at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.processKeyEvent(KeyBindingDispatcher.java:647)
    at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.filterKeySequenceBindings(KeyBindingDispatcher.java:439)
    at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher$KeyDownFilter.handleEvent(KeyBindingDispatcher.java:96)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
    at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1280)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1059)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1084)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1069)
    at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1111)
    at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1107)
    at org.eclipse.swt.widgets.Widget.wmChar(Widget.java:1536)
    at org.eclipse.swt.widgets.Control.WM_CHAR(Control.java:4875)
    at org.eclipse.swt.widgets.Canvas.WM_CHAR(Canvas.java:345)
    at org.eclipse.swt.widgets.Control.windowProc(Control.java:4753)
    at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:340)
    at org.eclipse.swt.widgets.Display.windowProc(Display.java:5002)
    at org.eclipse.swt.internal.win32.OS.DispatchMessage(Native Method)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3630)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1154)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1045)
    at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
    at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:644)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
    at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:551)
    at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:156)
    at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:152)
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:136)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:659)
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:596)
    at org.eclipse.equinox.launcher.Main.run(Main.java:1467)

However, I don't know what operation I did that corresponds to that. It was several minutes before I decided to look in the log file. It's clearly a response to a "jump" operation, but I don't know exactly what I was testing at that point.

I've tried multiple tests now, and I can only produce the "No method found" message.

mweirauch commented 2 years ago

I am running into the same issue. I am basically used to hitting "Ctrl+R" to run the tests for a class. (Modal-Message: No tests found with test runner 'Junit 5'.)

"Ctrl+j" or "Ctrl+u" don't work either. It seems to be the case that MoreUnit does not seem to be able to find the corresponding test class.

What happens when the create new test file wizard appears is, as what was described, that the finish button is deactivated, because the file exists. If you change the test file name and then back, you'll see a message stating the file already exists.

Another indicator for that is that the label decoration for "Tested File Indicator (MoreUnit)" also does not work. No file in the Package Explorer is "labeled" with that little green rectangle.

Eclipse 2021-12 and STS 4.13.1 (via update site)

Tarball commented 2 years ago

I'm also experiencing the same behavior in MoreUnit 3.3.0 and 3.3.1. Reverting to MoreUnit 3.2.0 restores the previous working behavior.

Eclipse 2021-12

kleese commented 2 years ago

Same problem here with MoreUni 3.3.1 with: Spring Tool Suite 4 Version: 4.13.1.RELEASE Build Id: 202201311654

Based on Eclipse Platform Version: 4.22.0.v20211124-1800 Build id: I20211124-1800

davidmichaelkarr commented 2 years ago

The lack of responses to this from people who maintain the plugin makes me think it's possible this has become abandonware. I sent a note to their support email a while ago, but I didn't get a response.

Tarball commented 2 years ago

This appears related to changes made for #41, specifically these: https://github.com/MoreUnit/MoreUnit-Eclipse/commit/2ac1539c52f96593458f7716b559db49990cad66#diff-1b1d762a0f351062be32f9c5ce4d4875363d7059edd92a67f90a22faf15d54efL38

Previously, the compilation unit was passed to getSearchScope(), which ends up doing the lookup from the CUT folder to the test folder. The result was a searchScope correctly set to the test folder. Now, a lookup is done from the CUT folder to the test folder using preferences.getTestSourceFolder() first, but then the results of that are passed into getSearchScope() which ends up doing the reverse logic, mapping the test folder back to the CUT folder. The result is searchScope is set to the CUT folder and the test class is not found there.

Reverting these lines appears to resolve the problem for my use-case (CUT and tests are in two separate projects).

Based on this, 3.3.0 seems to be the best version to use for now to work around this, since it adds support for newer versions of eclipse and doesn't include #41. I was wrong about 3.3.0 experiencing the same issue when I posted above.

apupier commented 2 years ago

The lack of responses to this from people who maintain the plugin makes me think it's possible this has become abandonware.

Currently, I'm the only relatively active maintainer but with very very low available time. if a Pull request is provided, i can have a look and do a release but I rarely have time to investigate on issues.

I sent a note to their support email a while ago, but I didn't get a response.

Can you precise which mail support you used? I'm not aware of any. I guess I will remove it from where it is mentioned.

apupier commented 2 years ago

Previously, the compilation unit was passed to getSearchScope(), which ends up doing the lookup from the CUT folder to the test folder. The result was a searchScope correctly set to the test folder. Now, a lookup is done from the CUT folder to the test folder using preferences.getTestSourceFolder() first, but then the results of that are passed into getSearchScope() which ends up doing the reverse logic, mapping the test folder back to the CUT folder. The result is searchScope is set to the CUT folder and the test class is not found there.

thanks for the analysis. If I understand well, it means that the searchScope is not well defined when jumping from test class to tested class.

davidmichaelkarr commented 2 years ago

Can you precise which mail support you used? I'm not aware of any. I guess I will remove it from where it is mentioned.

https://moreunit.github.io/MoreUnit-Eclipse/#about

drapichrust commented 2 years ago

I can confirm that that there is some weird issue with #41 fix. CorrespondingTypeSearcher should search in the "opposite" source folders. When the compilationunit provided is a test then searchScope should contain all possible source folders and vice versa when the compilationunit is a main class then searchscope should contain test source folders.

With the additional line the CorrespondingTypeSearcher always searches in main folders never in tests.

Madjosz commented 1 year ago

Since this bugs me for years now I created a patched JAR including PR #164: https://github.com/Madjosz/MoreUnit-Eclipse/releases/tag/v3.3.1-patched

davidmichaelkarr commented 1 year ago

I'd rather we got this to a point where we could create a local update site. I'm not very experienced with PDE. I managed to figure out how to build another plugin, because it had a "site.xml" file, and I know what to do with that. I don't understand how the MoreUnit plugin gets built. Does anyone have any idea?

phermsdorf commented 1 year ago

Maybe @apupier could have a look at the PR and then create a new release?

davidmichaelkarr commented 1 year ago

Well, I think I figured out the basic process for building it, but the environment on my work laptop makes it hard.

I noticed that one of the subprojects was "org.moreunit.build", so I looked at the files there, and I found a README.txt. This describes the process for releasing it, which is done entirely in a single script. They also show the mvn command line for releasing the "HEAD" of the branch, but I only want to be able to build it locally. Instead of doing "mvn deploy", I tried doing "mvn package". This has problems on my laptop because it is normally behind a VPN firewall. I was able to disconnect my VPN when running the build, but it still fails to connect to the remote sites needed to just do the build. It's not clear what I have to hack to get this to work.

Madjosz commented 1 year ago

I also tried to provide it on a local update site but the build job seems to be bound to deploy to the official update site and I couldn't bother to inspect and adjust everything to work with my local setting. Also the build job failed at swtbot so I was glad that it built every project I needed up to that point at least. Since also installing via dropins did not work I went with patching the jars as only 4 classes (12 including inner classes) were affected, it worked out of the box and I avoided all that PDE hustle.

Nevertheless I would welcome an official release of 3.3.2 including all the open PRs.

davidmichaelkarr commented 1 year ago

Ok, well, if I were to just use this patch that you provide, it's not clear exactly what jar file(s) I need. I looked at the first PR you refer to, and I looked at one of the files changed in that PR, and I then looked inside that "org.moreunit_3.3.1.jar", and that class was not in that jar, so I'm not sure what I'm looking at here.

apupier commented 1 year ago

Maybe @apupier could have a look at the PR and then create a new release?

I'm sorry, I do not know when I can allocate some time to work on this. I can provide admin maintainers rights to motivated people from this discussion

davidmichaelkarr commented 1 year ago

@Madjosz , could you provide more detailed instructions about what exactly needs to be installed where?

Madjosz commented 1 year ago

I wrote it in the release:

The JARs can be directly copied into the plugins directory in Eclipse, overwriting the installed v3.3.1.

(You need to have official MoreUnit v3.3.1 installed first from anywhere)

What I didn't include is the part of #109 for the org.moreunit.extension because I don't have it installed.

davidmichaelkarr commented 1 year ago

And after all that, putting those two jars into the plugins directory and restarting had no effect on the main issue I have. Pressing Ctrl-j (jump to test/source) just brings up the test creation dialog, instead of going to the existing test class. That dialog also has the "Next" and "Finish" buttons greyed out.

Madjosz commented 1 year ago

I am sorry to hear that. As they say "works on my machine". Maybe there is yet another source for this issue which has to be fixed.

RoiSoleil commented 11 months ago

Maybe @apupier could have a look at the PR and then create a new release?

I'm sorry, I do not know when I can allocate some time to work on this. I can provide admin maintainers rights to motivated people from this discussion

If you want i have good knowledge in Tycho, Maven and Eclipse plugin.And i actually use this plugin in Eclipse so i could help to create a new feature and maintain the plugin.

davidmichaelkarr commented 11 months ago

Speaking as just a user, I would certainly appreciate that.

I don't know whether @apupier just hasn't seen this yet, but it might help if you could figure out why this works for some people (apparently) and not for others (at least me). I would certainly be willing to test beta versions, and I would very much appreciate learning how to troubleshoot and step through this code, if deeper analysis is needed (I have many years of Java development, just not enough in Eclipse plugin development to figure this out on my own).

RoiSoleil commented 11 months ago

Speaking as just a user, I would certainly appreciate that.

I don't know whether @apupier just hasn't seen this yet, but it might help if you could figure out why this works for some people (apparently) and not for others (at least me). I would certainly be willing to test beta versions, and I would very much appreciate learning how to troubleshoot and step through this code, if deeper analysis is needed (I have many years of Java development, just not enough in Eclipse plugin development to figure this out on my own).

If you want there is a latest SMAPSHOT build available here for test : https://github.com/MoreUnit/MoreUnit-Eclipse/releases/tag/latest

davidmichaelkarr commented 11 months ago

Oh, my. It works.