B4J Question @Test annotation

Discussion in 'B4J Questions' started by walterf25, Nov 3, 2018.

  1. walterf25

    walterf25 Well-Known Member Licensed User

    Hello everyone, i decided to post this as i am in the middle of wrapping a library to automate UI Testing and Unit testing, i have figured a lot of the needed things and i am now able to install and launch a test application using B4J, the applications gets installed and deployed on my Android phone (It is possible to test B4i apps, but not tested yet).

    The library i am wrapping is Appium http://appium.io/ there is a bit of set up that needs to be done, but once everything is set up, it runs fantastic.
    The purpose of this library is to automate Application testing, combined with TestNG it becomes a great tool to test cases, once i figure everything out I will post the library and explain why i decided to research and wrap this library.

    For now i'am stuck trying to figure out how to go around defining the test methods within the library but at the same time to define them as @test methods, this is an annotation from the TestNG jar file, and every method defined like this is run and the results recorded in an html file automatically generated by the library, this html is a test report that records which test methods passed and which ones failed. At the moment i'am only able run this tests from within Eclipse.

    This is where I need help, i know B4X doesn't allow us to use annotations like this @test, it would be great if we were able to, but that's probably a topic for some other time.
    What i am trying to figure out is how to accomplish this somehow in B4J. My library contains 3 classes, one class is a TestListener which implements ITestListener from TestNG jar file, this class gets called everytime a test method is performed and the library asserts whether the test passed or failed.

    Again in order for the test methods to be included in the test cases they need to have the @test annotation at the beginning of each method sub.
    Anyone has any ideas on how i should go about this, this is the one thing that is keeping me from finalizing this library. One thing I tried is declaring the test method with inline Java and this seems to work but it will not work for the methods where the appium driver and capabilities need to be initialized and instantiated first, besides the idea of this is to have everything working without having to type any inline java code.

    Any thoughts, ideas, anyone....?

    Thanks,
    Walter
     
    amaxco likes this.
  2. Roycefer

    Roycefer Well-Known Member Licensed User

    My idea was to write a B4J app that you would call as a CustomBuildAction after the .java files were generated but before they were compiled into .class files. This app would convert '@test comments in B4J modules into @test annotations in the corresponding .java files. Unfortunately, there is no CustomBuildAction step at the required point in the compilation process. Maybe you can ask Erel to add a CustomBuildAction step at that point. Or just ask him to allow annotations.

    As a sidenote, have you tested this with resumable subs?
     
    walterf25 and amaxco like this.
  3. walterf25

    walterf25 Well-Known Member Licensed User

    I'm not very familiar with the CustomBuild feature, there has to be an easy way to do this, i have not tested with Resumable subs, not sure what benefit this would have.

    My next thought was to just implement the testing part by building a custom class which asserts all the testing cases, i think i saw a post in the B4A forum about someone doing something similar, where he first finds all the classes that start with a certain prefix and then going through each class finding all the methods that also start with a certain prefix and instantiating each class and executing each method, but I think this would be a very tedious process, i would really love to implement all this within the wrapped library, i think it would save us all a lot of time, are you familiar with Appium at all?

    Walter
     
  4. Roycefer

    Roycefer Well-Known Member Licensed User

    Based on my understanding of how ResumableSubs work, I don't think this unit testing would work with ResumableSubs. But I wanted to know if you had actually tested this and come to the same conclusion.

    No, I haven't worked with Appium before. But it sounds like you have it working in Eclipse/Java so it should work (except for with ResumableSubs) in B4J, if only we could get @test annotations. Adding annotations is just a matter of modifying a text file (.java) before it is compiled into an executable file (.class and then .jar). CustomBuildActions allow you to do stuff (usually in a batch file or an executable) at certain steps in the B4J compilation process. It would be a simple matter write a program that performs those text file modifications except that B4J's build process doesn't have a slot for CustomBuildActions at the point where .java files have been generated but before .class files are compiled. Maybe you can get Erel to add that in.

    Another option that I haven't tested is running the compilation twice. After the first compilation, you could make the mods to the .java files (via a B4J app) then set them to read-only so that they aren't deleted during the next compilation. Then compile again and run. You could probably test this by manually adding some annotations to a .java file and manually setting it to read-only and see if 2nd compilation completes and behaves normally. If it does, then adding those annotations with a B4J app should be easy.
     
    walterf25 likes this.
  5. walterf25

    walterf25 Well-Known Member Licensed User

    Seems like too much hassle, it shouldn't have to be this difficult, the point of this library is to make things easier, i think i will have to just write a custom library that asserts all the test methods and write the results to an html file for reporting, what a bummer, i was hoping to use the TestNG class for this as it automatically writes everything for you.

    This is what I tried today, i did some more research and there's another annotation named @DataProvider, with this annotation you can basically write another method which would return parameter of type Object, this annotation defines the test name to which the returned parameter should be passed, the method of course has to have the @test annotation, so this is what I tried so far.

    Code:
    @DataProvider(name = "test1")
        
    public static Object[][] PreTest(String[] asserts){
            //ba.raiseEvent(
    null"test1_test", new Object[0]);   this code fails because the whole class is started from the testng class and it fails at (ba) because it hasn't              //been instantiated or initialized, don't know how to do that
    return new Object[][]{{asserts[0],asserts[1]}};
        }
    when the above code is executed it looks for the @test method with the (dataProvider = "test1") name and it passes the parameters to it

    Code:
    @Test(dataProvider = "test1")
        
    public static void TestCase(String text1, String text2){
            BA.Log(
    "running test1 from within java...");
            Assert.assertEquals(text1, text2);
            //mba.raiseEventFromUI(
    null, EventName + "_test", new Object[]{});
        }
    This seems to work if I run it within the java code in eclipse, what I tried to do was in the @DataProvider sub or method, i tried raising an event so that I can return the parameters from within B4J, the only problem is that I get an error when the event tries to be raised because (ba) is not instantiated when the test methods are run, not sure how to do this so that it doesn't give me a null pointer exception.

    Any ideas?

    Walter
     
  6. Roycefer

    Roycefer Well-Known Member Licensed User

    Can you pass the calling class' ba as an additional parameter to PreTest? So that it looks like
    Code:
    @DataProvider(name = "test1")
    public static Object[][] PreTest(BA ba, String[] asserts){...
    ?
     
    walterf25 likes this.
  7. walterf25

    walterf25 Well-Known Member Licensed User

    No, i tried that and it throws an an exception.

    Walter
     
  8. Roycefer

    Roycefer Well-Known Member Licensed User

    Is all this happening inside Process_Globals?
     
    walterf25 likes this.
  9. walterf25

    walterf25 Well-Known Member Licensed User

    I'm not sure i understand your question, what do you mean is all this happening inside Process_Globals, is what exactly happening inside Process_Globlas?

    Walter
     
  10. Roycefer

    Roycefer Well-Known Member Licensed User

    The calls to these static methods. Are they occurring inside Process_Globals? I'm guessing that they're happening before there's a valid ba to pass.
     
  11. walterf25

    walterf25 Well-Known Member Licensed User

    Ah i see what you mean, yes the variables are being declared inside the Process_Globals.

    Walter
     
  12. Roycefer

    Roycefer Well-Known Member Licensed User

    And that is causing those static methods to be called before Process_Globals returns? If so, that's probably why ba isn't initialized yet.
     
  13. walterf25

    walterf25 Well-Known Member Licensed User

    I actually got something working just a moment ago, using the @DataProvider annotation and raising an event sub from B4J, the sub will return the parameters that the DataProvider passes to the @test Method, I wonder if @Erel would have some time to give his opinion on this, I know he's probably too busy but it would be great to know how likely it would be to get this annotations included in B4X.

    Walter
     
  14. JackKirk

    JackKirk Well-Known Member Licensed User

Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice