I created a Tellurium TestNG project and could not reproduce your problem.
Here are my html snippet, Ui Module, and test case.
HTML: (resources/org/telluriumsource/html/Dynamic.html)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
</head>
<body>
<table class='keyValueTable'>
<tr>
<td>AAA</td>
<td>111</td>
</tr>
<tr>
<td>BBB</td>
<td>222</td>
</tr>
<tr>
<td>CCC</td>
<td>333</td>
</tr>
</table>
<div id="view">
<p>
<a id=”111_222”>View</a>
</p>
<p>
<a id=”333_444”>View</a>
</p>
<p>
<a id=”555_666”>View</a>
</p>
</div>
</body>
</html>
UI Module:
class DynamicModule extends DslContext {
public void defineUi(){
ui.Table(uid: "keyValue", clocator: [class: "keyValueTable"]){
TextBox(uid: "{row: any, column: 1} as p1, var key", clocator: [text:
"key"], self: "true")
TextBox(uid: "{row: any, column: 2} as p2, var value", clocator:
[text: "value"], self: "true")
}
ui.List(uid: "Views", clocator: [tag: "div", id: "view"], separator:
"p"){
UrlLink(uid: "{any}, var view_id", clocator: [id: "view_id", text:
"View"])
}
}
}
Test Case:
public class DynamicTestNGTestCase extends TelluriumMockTestNGTestCase {
private static DynamicModule dm;
@BeforeClass
public static void initUi() {
registerHtml("Dynamic");
dm = new DynamicModule();
dm.defineUi();
useTelluriumEngine(true);
useTrace(true);
}
@Test
public void getAllText(){
String[] texts = dm.getAllTableCellText("keyValue");
assertNotNull(texts);
for(String text: texts){
System.out.println("Text: " + text);
}
}
@AfterClass
public static void tearDown(){
showTrace();
}
}
Output:
Parse configuration file: TelluriumConfig.groovy from project root directory
Configure UI Object Builders using configuration
Configure widget modules using configuration
Configure event handler using configuration
Configure data accessor using configuration
Configure dispatcher using configuration
Configure Embedded Selenium Server using configuration
Warning: No user-extensions.js
log4j:WARN No appenders could be found for logger
(org.openqa.selenium.server.SeleniumServer).
log4j:WARN Please initialize the log4j system properly.
Configure Selenium Client using configuration
TE: Name: getAllTableBodyText, start: 1271636312536, duration: 31ms
TE: Found exact match for UI Module 'keyValue':
{"id":"keyValue","relaxDetails":[],"matches":1,"relaxed":false,"score":100.0,"found":true}
Text: AAA
Text: 111
Text: BBB
Text: 222
Text: CCC
Text: 333
TE: Start Time: 1271636312536
End Time: 1271636312567
Total Runtime: 31ms
Name: getAllTableBodyText, count: 1, total: 31ms, average: 31ms
===============================================
Custom suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================
On Sun, Apr 18, 2010 at 8:02 PM, Jian Fang <[email protected]> wrote:
> Seems your 0.7.0 snapshot is not the latest one because the line number of
> the following line in UiObject.groovy is 284, not 234 as shown in the
> exception stack trace.
>
>
> println(i18nBundle.getMessage("Container.CannotFindUIObject" , {[child ,
> this.uid]}))
>
> The command for a tellurium testNG project should be as follows.
>
> mvn archetype:create -DgroupId=your_group_id -DartifactId=your_artifact_id
> -DarchetypeArtifactId=tellurium-testng-archetype
> -DarchetypeGroupId=org.telluriumsource -DarchetypeVersion=0.7.0-SNAPSHOT
> -DarchetypeRepository=http://maven.kungfuters.org/content/repositories/snapshots
>
>
> Thanks,
>
> Jian
>
> On Sun, Apr 18, 2010 at 5:45 AM, tetsuo <[email protected]> wrote:
>
>> Thanks for your responses Jian,
>>
>> I have tried your suggestion to ' validate the key value pairs from
>> the table' by defining a UI module as:
>>
>> ui.Table(uid: "keyValue", clocator: [class: "keyValueTable"]){
>> TextBox(uid: "{row: all, column: 1}", clocator: [tag: 'td'],
>> self: "true")
>> TextBox(uid: "{row: all, column: 2}", clocator: [tag: 'td'],
>> self: "true")
>> }
>>
>> I am however seeing a strange error message in my test result. I don't
>> know if a stack will suffice but I will include it here in case it
>> looks familiar to anyone.
>>
>> I generated a 0.7.0 snapshot testng maven project using the maven
>> tellurium testng archetype and have been sucessfully executing a basic
>> test, but now that I am trying to interact with an html table I am
>> seeing this rather odd error:
>>
>> groovy.lang.MissingPropertyException: No such property: i18nManager
>> for class: org.tellurium.object.TextBox
>>
>> Any idea what I might be doing wrong here? I am using everything out
>> of the box, including TelluriumConfig.groovy
>>
>> The full stack is as follows:
>>
>> groovy.lang.MissingPropertyException: No such property: i18nManager
>> for class: org.tellurium.object.TextBox
>> at
>>
>> org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:
>> 49)
>> at
>>
>> org.codehaus.groovy.runtime.callsite.GetEffectivePogoPropertySite.getProperty(GetEffectivePogoPropertySite.java:
>> 71)
>> at
>>
>> org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:
>> 240)
>> at org.tellurium.object.UiObject.walkTo(UiObject.groovy:238)
>> at org.tellurium.object.UiObject$walkTo.call(Unknown Source)
>> at
>>
>> org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:
>> 43)
>> at
>>
>> org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:
>> 116)
>> at
>>
>> org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:
>> 128)
>> at org.tellurium.object.List.walkTo(List.groovy:341)
>> at org.tellurium.object.List$walkTo.call(Unknown Source)
>> at
>>
>> org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:
>> 43)
>> at
>>
>> org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:
>> 116)
>> at
>>
>> org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:
>> 128)
>> at org.tellurium.object.Container.walkTo(Container.groovy:156)
>> at org.tellurium.object.Container$walkTo.call(Unknown Source)
>> at org.tellurium.dsl.UiDslParser.walkTo(UiDslParser.groovy:69)
>> at org.tellurium.dsl.UiDslParser$walkTo.call(Unknown Source)
>> at
>>
>> org.tellurium.dsl.BaseDslContext.walkToWithException(BaseDslContext.groovy:
>> 128)
>> at org.tellurium.dsl.BaseDslContext
>> $walkToWithException.callCurrent(Unknown Source)
>> at
>>
>> org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:
>> 47)
>> at
>>
>> org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:
>> 142)
>> at
>>
>> org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:
>> 154)
>> at
>>
>> org.tellurium.dsl.BaseDslContext.getAllTableCellText(BaseDslContext.groovy:
>> 716)
>> at org.tellurium.dsl.BaseDslContext
>> $getAllTableCellText.callCurrent(Unknown Source)
>> at
>>
>> org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:
>> 47)
>> at
>>
>> org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:
>> 142)
>> at
>>
>> org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:
>> 150)
>> at
>> module.DocumentShowModule.getValueForLabel(DocumentShowModule.groovy:
>> 35)
>> at
>>
>> test.DocumentShowTestCase.testDocumentLabelValuePairs(DocumentShowTestCase.java:
>> 37)
>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>> at
>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
>> 39)
>> at
>>
>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
>> 25)
>> at java.lang.reflect.Method.invoke(Method.java:597)
>> at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:
>> 580)
>> at org.testng.internal.Invoker.invokeMethod(Invoker.java:478)
>> at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:617)
>> at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:885)
>> at
>>
>> org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:
>> 126)
>> at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:
>> 110)
>> at org.testng.TestRunner.runWorkers(TestRunner.java:712)
>> at org.testng.TestRunner.privateRun(TestRunner.java:582)
>> at org.testng.TestRunner.run(TestRunner.java:477)
>> at org.testng.SuiteRunner.runTest(SuiteRunner.java:324)
>> at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:319)
>> at org.testng.SuiteRunner.privateRun(SuiteRunner.java:292)
>> at org.testng.SuiteRunner.run(SuiteRunner.java:198)
>> at org.testng.TestNG.createAndRunSuiteRunners(TestNG.java:821)
>> at org.testng.TestNG.runSuitesLocally(TestNG.java:788)
>> at org.testng.TestNG.run(TestNG.java:708)
>> at
>> org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:
>> 62)
>> at
>>
>> org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:
>> 141)
>> at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>> at
>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
>> 39)
>> at
>>
>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
>> 25)
>> at java.lang.reflect.Method.invoke(Method.java:597)
>> at
>>
>> org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:
>> 345)
>> at
>> org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:
>> 1009)
>>
>> Regards,
>>
>> Graham
>>
>> On Apr 10, 9:56 am, John <[email protected]> wrote:
>> > BTW, for your first question if you only need to validate the key
>> > value pairs
>> > from the table, you can simply define the UI module as
>> >
>> > ui.Table(uid: "keyValue", clocator: [class: "keyValueTable"]){
>> > TextBox(uid: "{row: all, column: 1}", clocator: [tag: td], self:
>> > "true")
>> > TextBox(uid: "{row: all, column: 2}", clocator: [tag: td], self:
>> > "true")
>> > }
>> >
>> > Then, call the following method to get back all table cell texts in
>> > one call.
>> >
>> > String[] texts = getAllTableCellText("keyValue")
>> >
>> > After that, you can loop through the array to validate the key value
>> > pairs.
>> > Make sure the table can be located by itself. If not, you can embed it
>> > inside
>> > some other UI module.
>> >
>> > More getAllTableCellText() examples can be found at
>> >
>> > http://code.google.com/p/aost/wiki/UserGuide070AppendixA#Custom_UI_Ob.
>> ..
>> >
>> > Thanks,
>> >
>> > Jian
>> > On Apr 9, 12:57 pm, Jian Fang <[email protected]> wrote:
>> >
>> >
>> >
>> > > I thought about it a bit. Two ways come to my mind.
>> >
>> > > The first one is to define an abstract UI object with variables such
>> as
>> >
>> > > ui.Table(uid: "keyValue", clocator: [class: "keyValueTable"]){
>> > > TextBox(uid: "{row: any, column: 1} as p1, var key", clocator:
>> [text:
>> > > "key"], self: "true")
>> > > TextBox(uid: "{row: any, column: 2} as p2, var value", clocator:
>> > > [text: "value"], self: "true")
>> > > }
>> >
>> > > In the above UI module, I defined two variables: key and value.
>> >
>> > > The abstract object could not be used directly and it must be
>> instantiated
>> > > with values binding
>> > > to the variables. I need to come up with a mechanism to instantiate
>> multiple
>> > > instances based on
>> > > the abstract objects. For example,
>> >
>> > > spawn "keyValue.p1", "KA", [key: "AAA"]
>> > > spawn "keyValue.p2", "V1", [key: "111"]
>> > > spawn "keyValue.p1", "KB", [key: "BBB"]
>> > > spawn "keyValue.p2", "V2", [key: "222"]
>> >
>> > > where "KA", "KB", "V1", and "V2" are new IDs. The new instances will
>> be
>> > > inserted into the Table "keyValue".
>> > > The key point here is to programmatically change the runtime UI
>> module.
>> > > After that, you can use
>> > > "keyValue.KA", "keyValue.V1", "keyValue.KB", and "keyValue.V2" to
>> reference
>> > > them.
>> >
>> > > The second option is to define a find() method for a UI object,
>> >
>> > > find(Map attributes)
>> >
>> > > In this way, the above method will first locate the UI object (i.e.,
>> the
>> > > table "keyValue" itself in the above example), then
>> > > find its children or descendants by the given attributes. Probably, we
>> can
>> > > also assign a temporal uid for each found
>> > > element like what getUiByTag does so that you can use the temporal uid
>> to
>> > > reference the found UI element.
>> >
>> > > This changes will not make its way into 0.7.0 RC2. I will see if I can
>> > > squeeze them in before 0.7.0 final release. If not, should
>> > > be included in 0.8.0.
>> >
>> > > Any suggestions and comments are welcome.
>> >
>> > > Thanks,
>> >
>> > > Jian
>> >
>> > > On Wed, Apr 7, 2010 at 11:19 PM, John <[email protected]>
>> wrote:
>> > > > Hi Graham,
>> >
>> > > > Great questions.
>> >
>> > > > Tellurium does support direct Selenium calls with the following
>> > > > method,
>> >
>> > > > def customDirectCall(String method, Object[] args);
>> >
>> > > > You can still programmatically generate the runtime xpath and then
>> > > > call the
>> > > > above method to Selenium directly.
>> >
>> > > > For more elegant solutions, it would be great if Tellurium could
>> > > > support dynamic
>> > > > attributes in the UI module. For example, for your first question,
>> if
>> > > > Tellurium UDL
>> > > > could define some attributes as dynamic and do lazy binding at
>> > > > runtime, your problem
>> > > > could be solved. But to be honest, I haven't thought of such use
>> cases
>> > > > yet. I will
>> > > > think it over and try to add this feature to UDL and core.
>> >
>> > > > For your second question, Tellurium provides the following method
>> >
>> > > > UiByTagResponse getUiByTag(String tag, Map filters);
>> >
>> > > > to return temporal uids for the giving tag and attributes. Then you
>> > > > can use these uids
>> > > > in the same way as other predefined uids in a UI module. More
>> details
>> > > > here,
>> >
>> > > >
>> http://code.google.com/p/aost/wiki/Tellurium070Update#Get_UIs_by_Tag_...
>> >
>> > > > I will follow up with you about my thoughts of dynamic attributes in
>> > > > UDL and core.
>> >
>> > > > Thanks,
>> >
>> > > > Jian
>> >
>> > > > On Apr 7, 9:57 pm, tetsuo <[email protected]> wrote:
>> > > > > Hi All,
>> >
>> > > > > My company is considering migrating from Selenium to Tellurium for
>> one
>> > > > > of our projects. However we are a little concerned about losing
>> some
>> > > > > test functionality that is currently enjoyed through the
>> utilization
>> > > > > of plain old Selenium. I would like to give some examples of the
>> test
>> > > > > functionality and then pose the question – how can I replicate
>> this
>> > > > > test functionality using Tellurium?
>> >
>> > > > > Example A - Verifying the content of a key/value pair table
>> >
>> > > > > I have a sequence of key/value pairs loaded from a test data file
>> into
>> > > > > a groovy map like so:
>> >
>> > > > > ['AAA': '111',
>> > > > > 'BBB': '222',
>> > > > > 'CCC': '333']
>> >
>> > > > > These pairs represent the expected content of a table to be
>> tested,
>> > > > > they might be rendered in html like so:
>> >
>> > > > > <table class='keyValueTable'>
>> > > > > <tr>
>> > > > > <td>AAA</td><td>111</td>
>> > > > > </tr>
>> > > > > <tr>
>> > > > > <td>BBB</td><td>222</td>
>> > > > > </tr>
>> > > > > <tr>
>> > > > > <td>CCC</td><td>333</td>
>> > > > > </tr>
>> > > > > </table>
>> >
>> > > > > Using Selenium I can programmatically generate the xpath for each
>> key/
>> > > > > value pair and assert the presence of the xpath.
>> >
>> > > > > String cellType = "td";
>> > > > > String tableLocator = "//tab...@id='" + tableId + "']";
>> > > > > String valueLocator = tableLocator + "//" + cellType +
>> > > > > "[...@class='label' and .='" + key + "']/following-sibling::"+
>> cellType;
>> >
>> > > > > Using Tellurium, how could I assert that the pairs in my test data
>> > > > > exist in the html table, considering that:
>> >
>> > > > > • The order of the pairs in the test data does not necessarily
>> > > > > represent the order of the pairs in the rendered html
>> > > > > • The test data files may be updated frequently, i.e. one day
>> there
>> > > > > may be 10 pairs, then the next there may be 30, and the new pairs
>> > > > > won’t necessarily be appended to the end of the test file.
>> > > > > • I don’t want to define each and every pair as elements
>> within a UI
>> > > > > module, the test must be data driven.
>> > > > > • The order of pairs in the test data may change i.e.
>> referencing
>> > > > rows
>> > > > > by index is too brittle.
>> >
>> > > > > Example B - Utilisation of programmatically generated element ids
>> >
>> > > > > Using Selenium if I have an element that I wish to interact with
>> and I
>> > > > > need to generate a unique id attribute for the element I can
>> > > > > programmatically generate the id and then compose some xpath to
>> > > > > reference said element. For example, if I have a series of links
>> with
>> > > > > composite ids:
>> >
>> > > > > <a id=”111_222”>View</a>
>> > > > > <a id=”333_444”>View</a>
>> > > > > <a id=”555_666”>View</a>
>> >
>> > > > > And my test data file looks like this
>> > > > > 111|222
>> > > > > 333|444
>> > > > > 555|666
>> >
>> > > > > Using Selenium I would programmatically generate the xpath
>> locators:
>> >
>> > > > > //inp...@id='${idLeft}_${idRight}']
>> >
>> > > > > And interact with the links using Selenium commands and the
>> generated
>> > > > > xpath.
>> >
>> > > > > Some questions:
>> >
>> > > > > 1. How could I interact with these links using Tellurium
>> (must be
>> > > > data
>> > > > > driven)
>> > > > > 2. Does the Tellurium API allow me to call Selenium commands
>> > > > directly?
>> >
>> > > > > I guess the crux of this post is about dynamic attributes in
>> Tellurium
>> > > > > tests. I really like the clean representation of the relevant
>> parts of
>> > > > > a DOM that Tellurium Modules bring, but I can't see how I can
>> perform
>> > > > > data driven testing with what appears to be largely static DOM
>> > > > > definitions.
>> >
>> > > > > Regards,
>> >
>> > > > > Graham
>> >
>> > > > --
>> > > > You received this message because you are subscribed to the Google
>> Groups
>> > > > "tellurium-users" group.
>> > > > To post to this group, send email to
>> [email protected].
>> > > > To unsubscribe from this group, send email to
>> > > > [email protected]<tellurium-users%[email protected]>
>> <tellurium-users%2bunsubscr...@googlegroups.com>
>> > > > .
>> > > > For more options, visit this group at
>> > > >http://groups.google.com/group/tellurium-users?hl=en.- Hide quoted
>> text -
>> >
>> > - Show quoted text -
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "tellurium-users" group.
>> To post to this group, send email to [email protected].
>> To unsubscribe from this group, send email to
>> [email protected]<tellurium-users%[email protected]>
>> .
>> For more options, visit this group at
>> http://groups.google.com/group/tellurium-users?hl=en.
>>
>>
>
--
You received this message because you are subscribed to the Google Groups
"tellurium-users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/tellurium-users?hl=en.