5 Replies Latest reply on May 29, 2013 11:36 AM by kpiwko

    Why does Arquillian add testing class itself into deployment?

    smikloso

      I am just too curious to forget about this ... the title says it, there are three scenarios:

       

      1) I specified @Deployment(testable = true)

       

      JUnit and all other servlet stuff is bundled into JAR internally by Arquillian. This makes sense.

       

      2) I specified @Deployment(testable = false)

       

      Nothing is added at all and @Deployment is totally untouched. This makes pretty much sense as well.

       

      However, the use case 3)

       

      @Deployment without anything specified, no argument, running tests as @RunAsClient adds testing class itself into deployment. So when I have the test class (where @Deployment is in the class named org.somecompany.MyTestClass), JAR file is enriched to contain that file, ending up with /org/somecompany/MyTestClass.class bundled there.

       

      This is just strange to me, I would say there are just two possibilities - testable = true / false. Enriched or totally not. Nothing "in between". I am quite sure of this behavior, I code some extension and internally I tripple checked this is happening ...

       

      It is said that testable = true is used by default when not specified differently, citation from the reference:

       

      As apposed to in-container mode which repackages and overrides the test execution, the as-client mode does as little as possible. It does not repackage your @Deployment nor does it forward the test execution to a remote server. Your test case is running in your JVM as expected and you're free to test the container from the outside, as your clients see it. The only thing Arquillian does is to control the lifecycle of your @Deployment.

       

      Any reasoning behind this? Maybe I am just missing something totally embarrasing .

        • 1. Re: Why does Arquillian add testing class itself into deployment?
          aslak

          @Deployment.testable = true|false controls the packaging. Either you test incontianer or you don't. testable = false implies @RunAsClient since there are no way to run incontainer without the added packaging.

           

          @RunAsClient only controls the run mode. It might sound strage to have @Deployable.testable=true and @RunAsClient, but the use case is mixed run modes. Where you e.g. do a Client call in one @Test, then a InContainer call in the next @Test to verify some internal state.

           

           

          But you are correct, we are missing some levels here. Similar problems with Jacoco. There is no way currently to collect coverage data from a testable=false deployment, since the infrastructure to collect it is not deployed. Warp has a similar thing as well, while the @Test run on client, it needs testable = true to add stuff for InContainer execution.

           

          We've started some design work on how this could work here https://issues.jboss.org/browse/ARQ-918

           

          What is your specific use case?

          • 2. Re: Why does Arquillian add testing class itself into deployment?
            smikloso

            @RunAsClient only controls the run mode. It might sound strage to have @Deployable.testable=true and @RunAsClient, but the use case is mixed run modes. Where you e.g. do a Client call in one @Test, then a InContainer call in the next @Test to verify some internal state.

            Yes I know about this and it is quite handy.

             

            My use case is like this:

             

             

            @RunWith(Arquillian.class)
            @RunAsClient
            public class ContainerTest {
            
                @Deployment(name = "android", testable = false)
                @TargetsContainer("android")
                public static Archive<?> createDeployment() {
                    return ShrinkWrap.createFromZipFile(JavaArchive.class, new File("apk-i-want-to-test.apk"));
                }
            
                @Test
                @InSequence(1)
                @OperateOnDeployment("android")
                public void test01(@ArquillianResource AndroidDevice android) {
                    Assert.assertTrue(android != null);
                }
            }
            
            

             

            So, I am deploying some APK. I am accessing that APK internally in deployment method (DeployableContainer.deploy(Archive<?> archive)) and I am sending it in an event from that deploy method to my custom deployer which installs that APK into the Android device.

             

            But, when I specify testable = true, this does not make sense right, that APK is enriched with JUnit staff and so on, that is not desired at all and does not make sense anyway. I do *not* modify APK in order to functionally test it. I am looking on that APK from outside (via instrumentation, that is not important here). I need totally untouched APK because when Arquillian adds there some resources (like testing class which I do not know why it is added there at all) I have to resign that APK file once again because the content of the APK file has changed. But this just does not make sense, I do not want to resign APK. I would have to then internally check every time if user "did not make a mistake" and did not forget to add "testable = false" annotation to @Deployment so no resigning is needed.

             

            So I have to obviously mark it as testable = false, in that way, the APK is not modified at all and that is what I want.

             

            But the point is, that I was thinking that it is sufficient to mark class as @RunAsClient and after that even I do not add testable = false to @Deployment, that APK archive will not be enriched at all. In other words, I did think that when I do not specify anything (omitting testable paramater completely) and I run it as @RunAsClient, that testable = false will be used internally automatically.

             

            testable = false implies @RunAsClient

             

            Does it hold other way around?

             

            Why is test class added to APK when I @RunAsClient and @Deployment.testable paramater is omitted?

            • 3. Re: Why does Arquillian add testing class itself into deployment?
              kpiwko

              It's an implication relation. You should know how boolean table for implication looks like ;-)

               

              So, if you set testable=false, it implies @RunAsClient. However, it does not work the other way.

               

              If you are thinking about having only @RunAsClient methods, why you don't simply mark @Deployment(testable=false) and omit @RunAsClient altogether?

              • 4. Re: Why does Arquillian add testing class itself into deployment?
                smikloso

                Because for ordinary user it is easier to grasp the concept of @RunAsClient so all he has to do is to annotate that class appropriately, instead of specificaly adding testable = false every time into @Deployment which is not so "straightforward". testable = false has to be there every single time ...

                 

                If he forgets to add @Deployment.testable = false, that testing class is automatically added into Archive<?> (as APK file under test) so I have to resign it because the content of the file as such has changed and it would fail to install on Android side afterwards because of it.

                 

                However, I could go for resigning the application under test every time, whenever test class is added or not ... but APK would end up with resources which are completely useless to be there.

                • 5. Re: Why does Arquillian add testing class itself into deployment?
                  kpiwko

                  I don't see how adding @RunAsClient to test class helps here. You still need to add it to every class, same as you need to do with @Deployment(testable=false).

                   

                  I agree though, that testable=true|false is counter intuitive name.