13 Replies Latest reply on Dec 20, 2007 8:15 PM by kragoth

    Static Analisys

    timdemeyer

      Hi,

      After attending Stan's talk at Javapolis last week, I decided to try out the static analysis part of JSFUnit and see if I could get a quick win out of this.

      I’ve discovered some small issues in our config here and there, and I’ve ended up with 2 final problems.

      1) I can’t get the ViewTestCase to work. He’s telling me our JSP’s aren’t well-formed. We do a fair bit of custom built templating so I guess that could be the problem. Is there any way to configure JSFUnit not to do this check?

      2) FacesConfigTestCase is failing because not all our sssion scoped Managed Beans are Serializable. Same here, are there any configuration possibilities?

      I think static analysis is a great idea, but the fact that I can’t configure what to analyze, and the fact that the test fails immediately when something’s off the hook, results in missing out on all the other goodies.

      So I guess if further configuration isn't possible, this is a request for a next release then, for a bit of configuration or for letting the analysis do its job entirely and finish with a report, instead of an immediate failure.

      Kind regards,

      Tim

        • 1. Re: Static Analisys
          dennisbyrne

          I'll give you a more complete answer in an hour or two when I have more time, but for now I can deal with #2. You want FacesConfigTestCase to fail because all session or application scoped data structures should be Serializable. When that test fails, it means "OK, we should fix this problem before we push this application to production". I will get to #1 in a little bit.

          • 2. Re: Static Analisys
            dennisbyrne

            I realize the tool could be a lot more useful if it didn't require the each template to be well formed XML, so I am open to suggestions. Stan has suggested JTidy, so maybe that's something I can look into over the xmas break.

            As far as being able to configure which tests not to run, I'd rather just override the test methods rather than deal w/ yet another configuration file to manage. Thoughts?

            Your "on error, resume next" idea is how I created it in the first place but I realized I could cram more features into the code if I just went w/ regular JUnit behavior. There is an issue in JIRA on this so perhaps you'll want to put a watch on it.

            • 3. Re: Static Analisys
              kragoth

              I've yet to even figure out how to get it to run :P

              Is there an example of how to do it?

              • 4. Re: Static Analisys
                ssilvert

                 

                "Kragoth" wrote:
                I've yet to even figure out how to get it to run :P

                Is there an example of how to do it?


                Have you seen this?
                http://wiki.jboss.org/wiki/StaticAnalysis

                Stan

                • 5. Re: Static Analisys
                  kragoth

                  Hi Stan,

                  Yeah I've read the link, but I don't know how to actually get the code to execute.

                  As in If i copy the code

                  public class ViewTestCase extends org.jboss.jsfunit.analysis.AbstractViewTestCase {
                  
                   private static Set absoluteViewPaths = new HashSet<String>() {{
                   add("C:/work/project/src/home.xhtml");
                   }};
                  
                   private static Set recursiveViewPaths = new HashSet<String>() {{
                   add("C:/work/project/src/views");
                   }};
                  
                   public MyViewTestCase() {
                  
                   super(absoluteViewPaths, recursiveViewPaths,
                   "C:/work/project/src/faces-config.xml");
                   }
                  
                  }
                  


                  How do I now run this code?

                  • 6. Re: Static Analisys
                    kragoth

                    I guess I should clarify... when I do try to run this code all i get is this.


                    Exception in constructor: testActions (java.lang.RuntimeException: Could not parse file 'D:\EVERST\LTLr\gekko-build\exploded\web\maintenance\capRateMaintenance.xhtml'
                    [gekko.junit] at org.jboss.jsfunit.analysis.AbstractViewTestCase.parseResources(AbstractViewTestCase.java:117)
                    [gekko.junit] at org.jboss.jsfunit.analysis.AbstractViewTestCase.<init>(AbstractViewTestCase.java:98)
                    [gekko.junit] at org.jboss.jsfunit.analysis.AbstractViewTestCase.<init>(AbstractViewTestCase.java:51)
                    [gekko.junit] at org.jboss.jsfunit.analysis.AbstractViewTestCase.<init>(AbstractViewTestCase.java:55)
                    [gekko.junit] at gekko.web.jsfunit.ViewTest.<init>(ViewTest.java:18)
                    [gekko.junit] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
                    [gekko.junit] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
                    [gekko.junit] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
                    [gekko.junit] at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
                    [gekko.junit] at junit.framework.TestSuite.createTest(TestSuite.java:61)
                    [gekko.junit] at junit.framework.TestSuite.addTestMethod(TestSuite.java:283)
                    [gekko.junit] at junit.framework.TestSuite.<init>(TestSuite.java:146)
                    [gekko.junit] at org.junit.internal.runners.JUnit38ClassRunner.<init>(JUnit38ClassRunner.java:69)
                    [gekko.junit] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
                    [gekko.junit] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
                    [gekko.junit] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
                    [gekko.junit] at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
                    [gekko.junit] at org.junit.internal.requests.ClassRequest.buildRunner(ClassRequest.java:33)
                    [gekko.junit] at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:28)
                    [gekko.junit] at org.junit.runners.Suite.<init>(Suite.java:55)
                    [gekko.junit] at org.junit.runners.Suite.<init>(Suite.java:41)
                    [gekko.junit] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
                    [gekko.junit] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
                    [gekko.junit] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
                    [gekko.junit] at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
                    [gekko.junit] at org.junit.internal.requests.ClassRequest.buildRunner(ClassRequest.java:33)
                    [gekko.junit] at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:28)
                    [gekko.junit] at junit.framework.JUnit4TestAdapter.<init>(JUnit4TestAdapter.java:28)
                    [gekko.junit] at junit.framework.JUnit4TestAdapter.<init>(JUnit4TestAdapter.java:21)
                    [gekko.junit] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
                    [gekko.junit] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
                    [gekko.junit] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
                    [gekko.junit] at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
                    [gekko.junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:387)
                    [gekko.junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch(JUnitTestRunner.java:912)
                    [gekko.junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:766)
                    [gekko.junit] Caused by: java.net.ConnectException: Connection timed out: connect
                    [gekko.junit] at java.net.PlainSocketImpl.socketConnect(Native Method)
                    [gekko.junit] at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
                    [gekko.junit] at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
                    [gekko.junit] at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
                    [gekko.junit] at java.net.Socket.connect(Socket.java:518)
                    [gekko.junit] at java.net.Socket.connect(Socket.java:468)
                    [gekko.junit] at sun.net.NetworkClient.doConnect(NetworkClient.java:157)
                    [gekko.junit] at sun.net.www.http.HttpClient.openServer(HttpClient.java:389)
                    [gekko.junit] at sun.net.www.http.HttpClient.openServer(HttpClient.java:516)
                    [gekko.junit] at sun.net.www.http.HttpClient.<init>(HttpClient.java:233)
                    [gekko.junit] at sun.net.www.http.HttpClient.New(HttpClient.java:306)
                    [gekko.junit] at sun.net.www.http.HttpClient.New(HttpClient.java:318)
                    [gekko.junit] at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:788)
                    [gekko.junit] at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:729)
                    [gekko.junit] at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:654)
                    [gekko.junit] at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:977)
                    [gekko.junit] at org.apache.xerces.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
                    [gekko.junit] at org.apache.xerces.impl.XMLEntityManager.startEntity(Unknown Source)
                    [gekko.junit] at org.apache.xerces.impl.XMLEntityManager.startDTDEntity(Unknown Source)
                    [gekko.junit] at org.apache.xerces.impl.XMLDTDScannerImpl.setInputSource(Unknown Source)
                    [gekko.junit] at org.apache.xerces.impl.XMLDocumentScannerImpl$DTDDispatcher.dispatch(Unknown Source)
                    [gekko.junit] at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
                    [gekko.junit] at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
                    [gekko.junit] at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
                    [gekko.junit] at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
                    [gekko.junit] at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
                    [gekko.junit] at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
                    [gekko.junit] at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:124)
                    [gekko.junit] at org.jboss.jsfunit.analysis.AbstractViewTestCase.parseResources(AbstractViewTestCase.java:115)
                    [gekko.junit] ... 35 more
                    [gekko.junit] )
                    




                    my class is like this

                    package gekko.web.jsfunit;
                    
                    import java.util.HashSet;
                    import java.util.Set;
                    
                    public class ViewTest extends org.jboss.jsfunit.analysis.AbstractViewTestCase {
                    
                     private static Set<String> absoluteViewPaths = new HashSet<String>() {{
                     add("D:/EVERST/LTLr/gekko-build/exploded/web/index.xhtml");
                     }};
                    
                     private static Set<String> recursiveViewPaths = new HashSet<String>() {{
                     add("D:/EVERST/LTLr/gekko-build/exploded/web");
                     }};
                    
                    
                     public ViewTest() {
                     super(absoluteViewPaths, recursiveViewPaths, "D:/EVERST/LTLr/gekko-build/exploded/WEB-INF/faces-config.xml");
                     }
                    }
                    




                    What am I doing wrong?

                    • 7. Re: Static Analisys
                      kragoth

                      Ok....it was just pointed out to me that maybe this error is because the static analysis is trying to download all the tlds or something.

                      I'm behind a proxy....so this is timing out.

                      Is there some way of storing the tlds locally so that it doesn't have to go out to the net to get them?

                      Or is this not even the problem?

                      • 8. Re: Static Analisys
                        dennisbyrne

                        The stack trace is telling you exactly what is wrong. It can't parse D:\EVERST\L
                        TLr\gekko-build\exploded\web\maintenance\capRateMaintenance.xhtml . This file probably has a xsd specified in the root element. The parser appears to be going to the Internet in order to find this file.

                        Can you post the contents of capRateMaintenance.xhtml ?

                        • 9. Re: Static Analisys
                          kragoth

                          Of course you are right!!!

                          My page is as follows

                          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                          <html xmlns="http://www.w3.org/1999/xhtml"
                           xmlns:ui="http://java.sun.com/jsf/facelets"
                           xmlns:h="http://java.sun.com/jsf/html"
                           xmlns:f="http://java.sun.com/jsf/core"
                           xmlns:rich="http://richfaces.org/rich"
                           xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
                           xmlns:s="http://jboss.com/products/seam/taglib"
                           xmlns:gekko="http://gekkoTagLibs.com">
                          
                           <ui:composition template="/web/templates/gekkoTemplate.xhtml">
                           <ui:define name="title">Cap Rate for Category/Subcategory Maintenance</ui:define>
                           <ui:define name="titlebar">Cap Rate for Category/Subcategory Maintenance</ui:define>
                           <ui:define name="content">
                           <h:form id="editSelectedCapRateForm">
                           <ui:decorate template="/web/enquiry/catSubcatEnquiry.xhtml">
                           <ui:define name="cScExtraFields">
                          
                           <h:outputLabel id="capDescriptionLabel" value="Cap Description" for="capDescriptionInput"/>
                           <s:decorate template="/web/templates/validationTemplate.xhtml">
                           <h:inputText id="capDescriptionInput"
                           value="#{capRateMaintenance.capRate.description}"
                           required="true"
                           label="Cap Rate Description"/>
                           </s:decorate>
                          
                           <h:outputLabel id="capRateLabel" value="Cap Rate (%)" for="capRateInput"/>
                           <s:decorate template="/web/templates/validationTemplate.xhtml">
                           <h:inputText id="capRateInput"
                           value="#{capRateMaintenance.capRate.rate}"
                           required="true"
                           label="Cap Rate (%)"/>
                           </s:decorate>
                          
                           <h:outputLabel id="effectiveDateLabel" value="Effective Date:" for="effectiveDateInput"/>
                           <s:decorate template="/web/templates/validationTemplate.xhtml">
                           <rich:calendar id="effectiveDateInput"
                           showInput="true"
                           enableManualInput="true"
                           datePattern="#{catSubcatDateSearch.dateFormat}"
                           currentDate="#{capRateMaintenance.capRate.subcategoryEffectivePeriod.effective}"
                           value="#{capRateMaintenance.capRate.subcategoryEffectivePeriod.effective}"
                           converter="GekkoDateConverter"
                           label="Effective Date"/>
                           </s:decorate>
                          
                           <h:outputLabel id="expiryDateLabel" value="Expiry Date:" for="expiryDateInput"/>
                           <s:decorate template="/web/templates/validationTemplate.xhtml">
                           <rich:calendar id="expiryDateInput"
                           showInput="true"
                           enableManualInput="true"
                           datePattern="#{catSubcatDateSearch.dateFormat}"
                           currentDate="#{capRateMaintenance.capRate.subcategoryEffectivePeriod.expiry}"
                           value="#{capRateMaintenance.capRate.subcategoryEffectivePeriod.expiry}"
                           converter="GekkoDateConverter"
                           label="Expiry Date"/>
                           </s:decorate>
                          
                           <h:outputLabel id="commentLabel" value="Comment:" for="commentInput"/>
                           <s:decorate template="/web/templates/validationTemplate.xhtml">
                           <h:inputText id="commentInput"
                           value="#{capRateMaintenance.capRate.comment}"
                           label="Comment"/>
                           </s:decorate>
                          
                           <rich:spacer/>
                           <rich:panel bodyClass="rightAlignNoPadding" style="border: 0px; padding: 0px; background-color:white;">
                           <h:commandButton id="cancelEditAveraging"
                           action="#{capRateMaintenance.cancelEditCapRate}"
                           value="Cancel"
                           immediate="true"/>
                           <h:commandButton id="saveAveraging"
                           action="#{capRateMaintenance.saveCapRate}"
                           value="Save">
                           <gekko:defaultAction/>
                           </h:commandButton>
                           </rich:panel>
                          
                           </ui:define>
                           </ui:decorate>
                           </h:form>
                           </ui:define>
                           </ui:composition>
                          </html>
                          



                          Ok, so I have my own taglib
                          xmlns:gekko="http://gekkoTagLibs.com"
                          


                          so what can I put in there to make it work?
                          It's my first time with my own taglib so I don't know what to do in this case.

                          how do I tell it that it's on the local machine?

                          • 10. Re: Static Analisys
                            kragoth

                            Well my own tag lib is not my only problem. I've tried with just the jsf tag libs and it still is going out to the internet to find them.

                            I really need to be able to force it to look on the local machine!


                            Is there any way around this?

                            • 11. Re: Static Analisys
                              dennisbyrne

                              Can you put an issue in the issue tracker on this one?

                              http://jira.jboss.com/jira/browse/JSFUNIT

                              • 12. Re: Static Analisys
                                kragoth

                                Ok, I've created an issue.

                                http://jira.jboss.com/jira/browse/JSFUNIT-67


                                So, I guess for the time being I can't use this feature. :)



                                Seeings as I can't test this, does JSFUnit work with SEAM beans? I don't have to have them in the xml?

                                • 13. Re: Static Analisys
                                  kragoth

                                  That should read *JSF UNIT Static Analysis*
                                  not just JSF Unit which I already know works with SEAM beans :)