How to obtain a PsiManager/Project/PsiFile, for a test case?
Check its
satisfiedBy(PsiElement element);
agains misc. PsiElements.
=> I need to produce those elements.
Mocks (stubs) are ok for simple elements (tokens, literal), but not for
complex one (block, expressions, methods, ..)
I thought about using :
PsiElementFactory factory = i_mgr.getElementFactory();
PsiStatement newStatement =
factory.createStatementFromText(i_newLineText, null);
return newStatement;
but I need a manager to obtain the element factory....
Hence my request.
The next step is to write/test IntentionAction(s) the same way
=> how to obtain a valid Project & PsiFile?
Alain
Note: if only JetBrains could share - part of - their editor test
framework, life would be easier, and plugins would come earlier.
]]>
请先登录再写评论。
If you use Intention API (com.intellij.codeInsight.intention), you have Project and PsiFile in isAvailable and invoke methods. You can get a PsiManager instance with PsiManager.getInstance(project).
Timur Zambalayev wrote:
>.. you have Project and PsiFile in isAvailable and invoke methods.
>
As I said, I need them in isolated junit testcases (writing the plugin
Test-First).
I'd like to write code like :
I don't know yet what I miss to make the element realistic enough (caret
position, anything else ?)
Alain
Outside IDEA getInstance() (e.g. PsiManager.getInstance(project)) methods won't work (see http://www.intellij.net/tracker/idea/viewSCR?publicId=7898 ).
Inside IDEA. Project - you can get one if your plugin is a ProjectComponent, also see ProjectManager. PsiFile - see PsiDocumentManager, FileDocumentManager.
> Outside IDEA getInstance() (e.g. PsiManager.getInstance(project))
methods won't work
I know. I should have titled my request :
"how to create a complex PsiElement outside of IDEA"
, because this is all I need.
> (see http://www.intellij.net/tracker/idea/viewSCR?publicId=7898 ).
That would be great, but as it doesn't come, I'd be happy with much less
: a simple way to create a PsiElement from code put in a String array
(see my example in previous msg).
Currently, I've created basic stubs (mocks) for simple classes. It
allowed me to write code like :
I can't go much further than that. I wish I could.
Alain
Well, seems we need to open some of our testcase framework that creates
UI-less application and opens UI-less project with all the PSI stuff
functional. Still it's a pretty much work and we'll consider if that
feaseable.
--
Best regards,
Maxim Shafirov
JetBrains, Inc / IntelliJ Software
http://www.intellij.com
"Develop with pleasure!"
"Alain Ravet" <alain.ravet.list@wanadoo.be> wrote in message
news:bf9d3f$m2q$5@is.intellij.net...
>
>
>
>
>
>
>
>
>
>
>
>
>
However, seems that framework is not what you really want. It takes too much
startup time, about 10s (once for all tests) and each test runs about 1s. It
is ok for regression testing but it doesn't really suit for test first.
--
Best regards,
Dmitry Peshehonov
JetBrains, Inc, http://www.intellij.com
"Develop with pleasure!"
"Maxim Shafirov" <max@intellij.net> wrote in message
news:bf9j1a$kap$1@is.intellij.net...
>
>
>
>
>
>
I've addressed my previous post to Alain Ravet and other TDDs.
--
Best regards,
Dmitry Peshehonov
JetBrains, Inc, http://www.intellij.com
"Develop with pleasure!"
Well personally, I've got 30 intentions and 140 inspections that I've been having to test by hand before ship. Anything you can do to automate the process would be greatly appreciated.
Thanks.
--Dave Griffith
Note:
Having not seen JetBrains' test framework, what follows may make no
sense, so correct if I'm wrong.
But if it makes sense, it would be worth considering.
Dmitry Peshehonov wrote:
> However, seems that framework is not what you really want.
> It takes too much startup time, about 10s (once for all tests)
> and each test runs about 1s. It is ok for regression testing but
> it doesn't really suit for test first.
Working Test-First, in baby steps, I don't need the full Monthy at this
stage.
Actually, I think I'd be happy with a
- a 20/80 subset of the framework,
that would be
- fast
and that that would allow me to
- create a "good enough" version of a PsiElement
corresponding to 1, 2, a few lines of code, a for loop, an if, a method...
Not sure if it's possible, or even if it make sense, but that would help
me a lot.
As my intentions' hooking process is based on Dave's IPP, I'm sure he
would also benefit/be happy with a fast 20/80 subset.
Alain
Hi, Alain.
>
I was just letting you know that this framework not for test-first.
>
>
>
There is no fast subset, it starts IDEA with UI and some conponents thown
away. For your purposes you may throw away some more but it will not make
start up much faster.
>
>
>
Well, you need to call
PsiElementFactory.getInstance().createXXXFromText(...) anyway. To get this
code work PsiElementFactory has to be initialized (and all components it
depends on), and this initialization takes time (start up). As one of your
test finishes framework resets components state, and that why tests runs so
long.
I'm just letting you know.
--
Best regards,
Dmitry Peshehonov
JetBrains, Inc, http://www.intellij.com
"Develop with pleasure!"
Dmitry
You:
> ..this framework (is) not for test-first.
Me:
>> Actually, I think I'd be happy with a a 20/80 subset ..
>> that would be fast and would allow me to
>> - create a "good enough" version of a PsiElement
>> corresponding to 1, 2, a few lines of code, a for loop, an if, a
method...
You:
> There is no fast subset, it starts IDEA with UI and some
> conponents .. you need to call .. and PsiElementFactory has
> to be initialized and .. this initialization takes time (start up).
> As one of your test finishes framework resets components state, and
> that why tests runs so long.
A 10+ sec. extra startup time looks huge, when you run your test every
minute, or two.
Do I really need to start the UI engine, to produce a ("limited" but)
valid (and "good enough") PsiElement?
The
"limited"
above means it's just a super mock, so I won't expect it to do
everything, like the real thing. Fair enough, as long as it's "good
enough". It's either that, or nothing, so I'd be happy with "that", and
its limitations.
Missing a lot of Psi.. related knowledge, I can't go the Mock way far
enough, but I wish I could write code like :
Case 1 seems easier to satify with a mock like solution.
Once again, missing a lot of Psi.. related knowledge, I can't say if it
makes any sense or is possible, but it would be d@|# useful.
Alain
Alain
>
>
We have the only one java parser the one working in Idea, and it needs
PsiManager to produce PsiElements, so now there is no way to obtain
PsiElements from code text (except initializing PsiManager and using it).
Currently we are working on hot swap for debugger - possible way to save
startup time with our current framework....
>
>
Anyway it is a very hard way, you have to create too large psi-trees...
>
>
>
--
Best regards,
Dmitry Peshehonov
JetBrains, Inc, http://www.intellij.com
"Develop with pleasure!"
Alain,
(Sorry for the delayed response -- was on vacation.)
I have the same problem in the tabifier plugin. Essentially I wanted a Psi tree outside of Idea (or at least independent of project and editor) for JUnit testing. I ended up writing a handful of mock Psi classes which implemented corresponding interfaces; most method implementations throw an exception to indicate they're unimplemented. (All I really needed was text, parent/child relationships, and offsets, so implemented these by hand.) Then I wrote a method that runs within Idea (as part of tabifier in debugging mode) that dumps the Psi tree as a Java class (program) which when run reconstructs the Psi tree using the mock objects. Now to test the plugin against some particular Java syntax, I put that syntax in a file, run the "dump Psi tree" function on it, move the generated Java class into my test environment, and in the TestCase setup() method call the generated Java class to create the mock Psi tree.
I went down the same path as you (to dynamically create a real Psi tree from a piece of text) but did not succeed for all the reasons you've discovered.
Disadvantages of my method is that changes to the real Psi interfaces have to be made in the mock structures every time it changes (which in Aurora is fairly frequent.) Also, I have not implemented any more than necessary for my limited purposes.
I would love it if IntelliJ would give us a way to be able to create a Psi tree from text without having to bring up the whole component/application/editor/project environment. I could use it also to implement a preview pane for tabifier alignment options (as IDEA does for certain code style options), as well as for testing. Alternatively, I'd be satisfied for testing with starting whatever environment the Psi code needs, regardless of the amount of time (10 seconds).
Meantime, perhaps what I wrote could be useful to you.
-Dave
PS - can you tell me where to find info on JetBrain's test environment? Is this something different from the typical plugin test environment of running two copies of Idea, one for the plugin and the other to debug the first?
We're currently working on some testing framework that will satisfy your
needs. It most probably will be released in next builds.
--
Best regards,
Maxim Shafirov
JetBrains, Inc / IntelliJ Software
http://www.intellij.com
"Develop with pleasure!"
"Dave Kriewall" <no_mail@jetbrains.com> wrote in message
news:31795504.1059178229946.JavaMail.itn@is.intellij.net...
>
>
Psi tree outside of Idea (or at least independent of project and editor) for
JUnit testing. I ended up writing a handful of mock Psi classes which
implemented corresponding interfaces; most method implementations throw an
exception to indicate they're unimplemented. (All I really needed was text,
parent/child relationships, and offsets, so implemented these by hand.)
Then I wrote a method that runs within Idea (as part of tabifier in
debugging mode) that dumps the Psi tree as a Java class (program) which when
run reconstructs the Psi tree using the mock objects. Now to test the
plugin against some particular Java syntax, I put that syntax in a file, run
the "dump Psi tree" function on it, move the generated Java class into my
test environment, and in the TestCase setup() method call the generated Java
class to create the mock Psi tree.
>
from a piece of text) but did not succeed for all the reasons you've
discovered.
>
to be made in the mock structures every time it changes (which in Aurora is
fairly frequent.) Also, I have not implemented any more than necessary for
my limited purposes.
>
tree from text without having to bring up the whole
component/application/editor/project environment. I could use it also to
implement a preview pane for tabifier alignment options (as IDEA does for
certain code style options), as well as for testing. Alternatively, I'd be
satisfied for testing with starting whatever environment the Psi code needs,
regardless of the amount of time (10 seconds).
>
>
>
Is this something different from the typical plugin test environment of
running two copies of Idea, one for the plugin and the other to debug the
first?
As the next build gets released you may use a framework described at
http://www.intellij.org/twiki/bin/view/Main/PluginsTestingFramework
Any questions/suggestions are appreciated.
--
Best regards,
Maxim Shafirov
JetBrains, Inc / IntelliJ Software
http://www.intellij.com
"Develop with pleasure!"
"Alain Ravet" <alain.ravet.list@wanadoo.be> wrote in message
news:bf985m$m2q$1@is.intellij.net...
>
Maxim,
I extended LightIdeaTestCase and called its setup() method from my setup() method. I received this error several times:
Where are the internalUtilities classes? I couldn't find them.
-Dave
Sorry, all those scrambling problems. To be fixed.
--
Best regards,
Maxim Shafirov
JetBrains, Inc / IntelliJ Software
http://www.intellij.com
"Develop with pleasure!"
"Dave Kriewall" <no_mail@jetbrains.com> wrote in message
news:135221.1060023162675.JavaMail.javamailuser@localhost...
>
method. I received this error several times:
>
>
Hi Maxim,
I'm trying to use LightIdeaTestCase in EAP build 896. My test subclass has the following constructor and setUp() method:
When calling super.setUp(), I get log4j problems.
1) First is that it cannot find the log4j package. I worked around by adding C:\IntelliJ-IDEA-896\lib\log4j.jar to my project libraries.
2) Next problem is that it cannot find the log4j.dtd file:
To work around this, I set the working directory to C:\IntelliJ-IDEA-896\bin.
3) Next it cannot find class com.jniwrapper.Parameter, so I added JNIWrap.jar to the project library list.
4) finally, the call to super.setup() succeeds and I finish my own initialization. However, after returning from my own setUp() method, I get the following exception:
Here I'm stuck -- I don't know why the assertion is failing. Can you suggest something?
Also, there's a LightIdeaTestCase.runBare() method which is not documented. Am I supposed to call this at some point?
Thanks-
-Dave
"Dave Kriewall" <no_mail@jetbrains.com> wrote in message
news:5451074.1060803301838.JavaMail.itn@is.intellij.net...
has the following constructor and setUp() method:
>
initialization. However, after returning from my own > > > setUp() method,
I get the following exception:
>
suggest something?
>
I think assertion has occured at TestCase.runTest (at line 138). But since
TestCase is JUnit's class then begining of stack trace is thrown away (up to
runTest call from LightIdeaTestCase).
documented. Am I supposed to call this at some point?
We override TestCase.runBare(), this method is called by JUnit framework
(refer to JUnit source/docs if you want to know what it for).
>
--
Best regards,
Dmitry Peshehonov
JetBrains, Inc, http://www.intellij.com
"Develop with pleasure!"
It's quite easy actually. Should have been validate all assertions have
message.
This because test name is taken from test method. And assertion failing
should say something like: test name should start with 'test'.
All you're have to do is remove constructor from your class.
BTW, there's easier way for what you're doing like this:
--
Best regards,
Maxim Shafirov
JetBrains, Inc / IntelliJ Software
http://www.intellij.com
"Develop with pleasure!"
"Maxim Shafirov" <max@intellij.net> wrote in message
news:bhfpt0$8fa$1@is.intellij.net...
>
No, the problem came from TestSuite code (select constructor to instantiate
test):
TestSuite first looks for constructor(String).
And (instantiate test with choosen constructor):
So when calling constructor with String parameters TestSuite doesn't call
setName.
Then TestCase.runTest code:
throws assertion failed.
--
Best regards,
Dmitry Peshehonov
JetBrains, Inc, http://www.intellij.com
"Develop with pleasure!"
You can easily create such a mock by hands.
--
Best regards,
Mike Aizatsky.
-
JetBrains, Inc / IntelliJ Software
http://www.intellij.com
"Develop with pleasure!"
That's great -- thanks for the suggestion!
However, the configureByFile method seems to assume the file is in a testData directory, and absolute pathnames aren't allowed. If I write
I get the following error:
but I moved PsiTestClass.java to the testData directory and changed the string parameter, so now it finds the file and builds the Psi tree properly. I can step through my tests and see that they succeed using the PsiFile obtained from getFile(). YEE-HAH! Thank you!
Now there's one remaining issue, dealing with log4j, which causes each test to fail. I receive the following error for each test:
Can you suggest a workaround?
Thanks very much!
-Dave
test to fail. I receive the following error for each test:
>
(#com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl).
>
com.intellij.testFramework.LightIdeaTestCase.tearDown(LightIdeaTestCase.java
:31)
com.intellij.testFramework.LightCodeInsightTestCase.tearDown(LightCodeInsigh
tTestCase.java:45)
com.intellij.testFramework.LightIdeaTestCase.d(LightIdeaTestCase.java:3)
com.intellij.testFramework.LightIdeaTestCase.a(LightIdeaTestCase.java:4)
com.intellij.testFramework.LightIdeaTestCase$2.run(LightIdeaTestCase.java)[/
pre]
Still, you need to have log.xml and log4j.dtd in working directory and
log4j.jar in classpath. Is it so?
Your guess was correct -- my working directory was reset. I must have right-clicked the class to run the JUnit test again instead of using the saved Run/Debug configuration.
Now however, whether it is correct or wrong, I get the following error. Why I didn't get it before is baffling, since I haven't changed any code. It occurs when executing the line
which caused no trouble before. Restarting IDEA makes no difference. The PsiTestClass.java file is still present in the testData directory, and has always been read-write. The PsiBasedTest class has no constructor, and the only thing it does in setUp prior to the offending line is to call super.setUp().
We usually do configureByFile in test method itself rather than setUp since
usually each test deals with its own file and for that matter running test
method is guarded by ApplicationManager.getApplication().runWriteAction(new
Runnable() {...}) automatically. If you'd like to configureByFile in setUp
you've to change the code like following:
--
Best regards,
Maxim Shafirov
JetBrains, Inc / IntelliJ Software
http://www.intellij.com
"Develop with pleasure!"
"Dave Kriewall" <no_mail@jetbrains.com> wrote in message
news:27858603.1060958626244.JavaMail.itn@is.intellij.net...
right-clicked the class to run the JUnit test again instead of using the
saved Run/Debug configuration.
>
Why I didn't get it before is baffling, since I haven't changed any code.
It occurs when executing the line
difference. The PsiTestClass.java file is still present in the testData
directory, and has always been read-write. The PsiBasedTest class has no
constructor, and the only thing it does in setUp prior to the offending line
is to call super.setUp().
>
That did it -- everything works wonderfully!
Thank you!
-Dave