premganz / SeleniumPageObjects

An implementation of the Page Object Pattern in Selenium along with a bunch of other features like KeyWords for oft used Webdriver calls, driver lifecycle management, effective logging and Test Script Templates
Other
2 stars 1 forks source link

TRS(TestResourceServer) references are too meddled in spo #27

Closed premganz closed 8 years ago

premganz commented 8 years ago

There is a need to externalize a tightly coupled design assumption of the library , namely the need to work with a "page" level validation. If we are denying this core design, we will be killing the spirit of the library, but it makes sense for us to make the text content provider for the 'expected value' of the text representation of each page configurable.

This was already dealt with in Issue 25. Now if we choose to work with the TRSContentProvider, we need to understand the architecture of the TRS and DDS complex. The TRS is a restful broker.period. Incidentally it also has in its resource path xls files whose data it serves. Apart from this exception, it simply forwards the requests to other servers which respond with replies. The currently active ones are an Apache httpd for python-cgi invocations and a DomainDocumentServer(DDS) which is a simple groovy contraption, a thread on a port kind of server.

Hence a generic way in which the TRS could be described to be is: -a http server that has a domain name and port eg: http://xyz:8080/ -what follows this prefix is the 'topic' (which can be datasourcebroking, externalserverbroking or docuserverbroking (subdivided as pages, event and datareques(see below for more details))) -this is followed by the actual url with or without query params.

The DDS can be generically described as : -a http server that has a domain name and port eg: http://xyz:8080/ -what follows this is one of the modules and actual query it handles, it works on this basic design: a) It maintains the application pages as plain text files which are templatable with placeholders. b) These placeholders are modified according to _events_ pushed to this server. The events should specify the _actor_ and the _eventName_ eg. http:xyz:8081/event/SettingsActor?Nightly&day=Monday c) It serves back templated pages by invocation of its pages module like /pages/other/ResultPage d) It is also a source of truth of application configuration and can serve back json data for invocation of its datarequest module like /datarequest/config.

I guess this might be confusing, but if we have some service that obeys these rules, we can make suitable invocations from the kw to get us desired results for instance

kw.getPageAsText() can simply do

http://xyz:8080/pages/other/ExitPage

The part of the url following pages is a purely functional thing which can be used by the application at runtime. The part before it is purely static and is configured in the AppConfig. But the module name is a bit abandoned here. I guess this needs to be defined in a file and served from there as a conceptual thing, because the model of (pages, event, datarequest), externalcalls, xlsAcces is something core to the architecture of the Application. Hence these will no longer be hardcoded anywhere in the framework but would be pulled from AppConfig, ready for overriding. Can we look for somekind of pre-named mapping here, where keys become unmodifiable and values can only be referenced, some kind of a table???

premganz commented 8 years ago

Fix given by a new class TRSModules which contain static Strings of the module names.

premganz commented 8 years ago

The possible fix could be something like this. We dont talk of servers at highlevel, we talk of serivices

So better to have some service interface like externalServices

interface ExternalService extends ExtensibleService{ enum ServiceModules{} ServiceMessage queryExternalScript(String query); String queryXlsData(String query); List queryXlsDataAsString(String query); String getPageText(String query); void sendDomainEvent(String experssion); Map<String,String> getDomainStateMap(String actor)

}

class ServiceMessage{ String topic; String payload; }

Now this external Service can be invoked from Now are we proposing a rigid interface for the external service, afterall, the calls of external scripts and xls are pretty much non-core for the framework. So I don't think the framework should assume an external service that need to offer them. I think in the impl, we can either throw unsupportedoperation exception in the overridden scenarios of applicaiton extension. So that would not be the primary issue with this approach.

The need for the ExternalService is that we are infact providing classes in the framework that queryup xls and make externalscript calls with Message object that goes back and forth. Hence the framework should be able to hook up to a proper service class which can be a point of control for the extending apps. I guess we can implement extensibleService too.

premganz commented 8 years ago

Undoing a lot of what was done earlier in this connection The TRS Modules file is deleted

The laison with TRS is a bit more complicated. in the sense that there are two areas of interaction. The Domain related ones should ideally be even more tightly coupled and the xls and external script runs should be loosely coupled. The xls and ext scripts were hence toned down and made as convenience calls routed through the ExternalScriptSvc. This takes just one or 2 methods generic like String callServer(String query). Nothing would be hardcoded into this service. No root urls and no module names. Everything needs to be passed along.

This is distinct from the DomainSvc which will have some really hardcoded methods like fetchPage(String query) and domain_event(). This is because the various methods in page_validation and getting out the current domain state are deeply coupled to the architecture of the spo itself. So this will be a more concrete service.

Now these two services would go into AppConfig. They are no longer reachable via kw. This is a major design decision. kw hitherto a main switchboard for all operations on the applications would now only represent the driver as an agent. The domain will be represented by the domainSvc, ExternalScriptSvc will be one more service.

The application now comes to have 3 pillars and not 2 Earlier the extending application would be happy to customize the "JunitScript" by extending and reconfiguring the kw injected into it. and the "Node3_ScriptRunner" to make changes to the AppConfig and the Default RunStrategy.

Now the services hitherto hardcoded like DriverFactory and ProxyServerController can be moved to be a part of the AppConfig. But thats into the future. The services created newly like the above can be embedded into the AppConfig allowing for overriding in the init(). This is via a ServiceFactory which will become part of the AppConfig.

premganz commented 8 years ago

This has actually caused some major changes to the application architecture, in that now we recognize quite nostalgically that kw would no longer be like the switchboard owing to growing complexities. We would have a servicefactory to provide with other services, which may in the future also become pluggable.

We have since reformatted the ExternalSvc scripts cutting down on a lot of flab and also the DomainSvc would now be a concrete part of the application . Made release major as 1.4.0 and closed this issue

premganz commented 8 years ago

On afterthought The refactoring in of new services into the SessionContext kind of sways the overall architecture of spo into a vague territory. We need to be clear of the design pattern we follow.

We have in the heart a command pattern where the runner is the ScriptRunner and the command is the SimpleScript . The second important pattern is a public SessionContext which contains an ApplicationConfiguration (appConfig) where everything for the session is configured. Then we use a "MEdiator" or ServiceHub design pattern, where we have all the services configured into KeyWords (which we will rename as ServiceHub). This will register the services and allow for different configurations of the service through dependencyInjection(using the init() method of the ExtensibleService).

This we will stick to, so the servicefactory moves from SessionContext to the ServiceHub in release 1.4.1