How to access views defined with a specific [plone.]browserlayer in test cases - testing

I'm new to testing and I'm trying to create a test for my Plone product for the first time.
I'm on Plone 3.3.
The basic test suite works, I can execute it without errors.
I followed this documentation : http://plone.org/documentation/kb/testing
...except that I'm writing my tests in Python classes instead of doctests.
My problem is that I cannot seem to access the views defined in my app (I get ComponentLookupError).
The problem seems to be with the "browserlayer" defined by my applications.
When I remove the layer="..." attribute from my configure.zcml, the test can access the views without problem. However, if I add it back, it doesn't work.
I guess that's because de browserlayer interface doesn't get applied to the request.
The only reference to this problem I found is in the tests for googlesitemap : http://dev.plone.org/collective/browser/googlesitemap/googlesitemap.common/trunk/googlesitemap/common/tests?rev=
The author seems to have made a custom ZCML file for the test, in which the layer="..." attribute has been removed. (which would work but it seems very bad having to maintain a separate zcml file for the tests)
In my test, I have included the following (taken from the googlesitemap tests), which passes :
from jambette.site.interfaces import IJambetteLayer # this is my browserlayer
from plone.browserlayer.utils import registered_layers
self.assertTrue(IJambetteLayer in registered_layers())
So I think my skin and browserlayer are registered correctly.
Is there anything I need to do so that the browserlayer will be applied to the request?

Browser layer interfaces are simply 'painted' onto the request with directlyProvides. Simply do so in your test setup before you look up the view:
from zope import interface
from jambette.site.interfaces import IJambetteLayer
...
directlyProvides(request, IJambetteLayer)

Related

How to test Vue "Services" mounted to root, accessed via Vue.prototype

First, I'd like to explain that I have a Vue component repository that is responsible for displaying data retrieved from an http service. Rather than the component itself managing the same data retrieval per instance and spamming the client with network requests, I've managed to find a solution which allows another component to be mounted to the root directly (which I've dubbed as a "Service" due to its similarity to Angular) to manage the data those components need instead. This works great and other components can access it via Vue.prototype (via this.$TestService.value). It has some caveats but for the most part it accomplishes exactly what I needed. This may be uncommon, but those that use Vuex are using a similar methodology and I don't want to use the store paradigm.
I've made a very simple Vue JsFiddle to show this in action...
https://jsfiddle.net/spronkets/8v31tcfd/18
Now, to the point... I'm using #testing-library/vue, #vue/test-utils, and Jest to test the components and get test coverage and now I get errors anytime I run the tests due to the service not existing on the Vue.prototype during the test execution. I don't want to mock out the functionality of the "Service" layer, so does anyone have a solution to test these root-mounted components? I've tried manually exporting the services (unmounted and mounted) and including them in the mock section as well as importing the files directly into the test files but the "Service" is always undefined when the component is trying to retrieve the value and ONLY during test execution...
I've also created a simple repository modelled after the Vue component repository I am working with below...
https://github.com/kcrossman/VueServiceExample
To get started, clone the repo and follow the README.md included in the repo. Thanks!
I would go against using the real service if it is asyncronous, but if you just want to register it to be available you can follow the mock instructions but instead of mocking with an object just import the real service. Although after seeing your TestService implementation you will need to separate the real service from the service registration and export it to be able to register it in local vue.
You need to create and prepare your custom Vue instance in your tests in order to use any custom functionalities in your unit tests (like stores, routers, and anything else). (You can use your real modules with the custom instance, don't have to mock anything.)
In your case you should create a new Vue instance with "createLocalVue" function from '#vue/test-utils' and apply your custom prototype functionalities on that. After that you can write proper test cases accessing that custom features as well.
Update:
For those that might be referring to this in the future, Vue Plugins might be a better solution for this kind of functionality.
I stumbled along this issue in GitHub and that led me to the fix I made below:
https://github.com/testing-library/vue-testing-library/issues/113
Specifically, this comment by user nikravi:
ok, I found the fix. The trick was to add
import Vue from "vue";
import Vuetify from "vuetify";
Vue.use(Vuetify);
and then the render() works without warnings.
After I manually imported Vue and set Vue.prototype.$TestService = TestService directly in the unit test, it got passed that error. Personally, I think this is pretty silly, but it worked.
After this worked, I also found that you can access the Vue instance directly within the render callback (from #testing-library/vue), so I finished on this code instead of importing Vue:
render(TestComponent, {}, vue => {
vue.prototype.$TestService = TestService;
});
I've included all the commits to solve my issue in the repo I posted previously:
https://github.com/kcrossman/VueServiceExample
Some of the tests were malformed but once I made those changes, the tests started to work and I updated some other files to be a bit nicer for people to refer to.

GO Unit testing structured REST API projects

I am trying to write nice unit tests for my already created REST API. I have this simple structure:
ROOT/
config/
handlers/
lib/
models/
router/
main.go
config contains configuration in JSON and one simple config.go that reads and parses JSON file and fills the Config struct. handlers contains controllers (i.e. handlers of respective METHOD+URL described in router/routes.go). lib contains some DB, request responder and logger logic. models contains structs and their funcs to be mapped from-to JSON and DB. Finally router contains the router and routes definition.
Now I was searching and reading a lot about unit testing REST APIs in GO and found more or less satisfying articles about how to set up a testing server, define routes and test my requests. All fine. BUT only if you want to test a single file!
My problem is now how to set up the testing environment (server, routes, DB connection) for all handlers? With the approach found here (which I find very easy to understand and implement) I have one problem: either I have to run tests separately for each handler or I have to write test suites for all handlers in just one test file. I believe you understand that both cases are not very happy (1st because I need to preserve that running go test runs all tests that succeed and 2nd because having one test file to cover all handler funcs would become unmaintainable).
By now I have succeeded (according to the linked article) only if I put all testing and initializing code into just one func per XYZhandler_test.go file but I don't like this approach as well.
What I would like to achieve is kind of setUp() or init() that runs once with first triggered test making all required variables globally visible and initialized so that all next tests could use them already without the need of instantiating them again while making sure that this setup file is compiled only for tests...
I am not sure if this is completely clear or if some code example is required for this kind of question (other than what is already linked in the article but I will add anything that you think is required, just tell me!
Test packages, not files!
Since you're testing handlers/endpoints it would make sense to put all your _test files in either the handlers or the router package. (e.g. one file per endpoint/handler).
Also, don't use init() to setup your tests. The testing package specifies a function with the following signature:
func TestMain(m *testing.M)
The generated test will call TestMain(m) instead of running the tests
directly. TestMain runs in the main goroutine and can do whatever
setup and teardown is necessary around a call to m.Run. It should then
call os.Exit with the result of m.Run
Inside the TestMain function you can do whatever setup you need in order to run your tests. If you have global variables, this is the place to declare and initialize them. You only need to do this once per package, so it makes sense to put the TestMain code in a seperate _test file. For example:
package router
import (
"testing"
"net/http/httptest"
)
var (
testServer *httptest.Server
)
func TestMain(m *testing.M) {
// setup the test server
router := ConfigureRouter()
testServer = httptest.NewServer(router)
// run tests
os.Exit(m.Run())
}
Finally run the tests with go test my/package/router.
Perhaps you could put the setup code that you want to use from multiple unit test files into a separate package that only the unit tests use?
Or you could put the setup code into the normal package and just use it from the unit tests.
It's been asked before but the Go authors have chosen not to implicitly supply a test tag that could be used to selectively enable function compiles within the normal package files.

How to pass an argument (e.g. the hostname) to the testrunner

I'm creating a unittest- and Selenium-based test suite for a web application. It is reachable by several hostnames, e.g. implying different languages; but of course I want to be able to test e.g. my development instances as well without changing the code (and without fiddling with the hosts file which doesn't work for me anymore, because of network security considerations, I suppose).
Thus, I'd like to be able to specify the hostname by commandline arguments.
The test runner does argument parsing itself, e.g. for chosing the tests to execute.
What is the recommended method to handle this situation?
The solution I came up with finally is:
Have a module for the tests which fixes the global data, including the hostname, and provides my TestCase class (I added an assertLoadsOk method to simply check for the HTTP status code).
This module does commandline processing as well:
It checks for its own options
and removes them from the argument vector (sys.argv).
When finding an "unknown" option, stop processing the options, and leave the rest to the testrunner.
The commandline processing happens on import, before initializing my TestCase class.
It works well for me ...

Application modules with Pyramid

I'm creating a workflow app with pyramid and i'm searching how to make the application modulable : meaning create a core app with sqlalchemy models, base forms with wtforms, and some base templates with mako.
The basic structure of the "Core" app is:
App_Core/core.ini
/setup.py
/...
/App_Core/
/__init__.py
/models.py
/forms.py
/utils.py
/templates/
/templates/base.mako...
/static/
/static/staticfiles...
My goal is to create 1 application per workflow which will be included in the Core app : it seems possible to do that via the includeme function provided with pyramid.
I want to include each workflow via the core.ini file, for example:
pyramid.includes =
workflow_app1
workflow_app2
workflow_app3
...
I defined an new app called workflow_app1 with the following structure:
worflow_app1/
/setup.py
/...
/workflow_app1/
/__init__.py
/models.py
/forms.py
/views.py
/templates/
/templates/workflow_app1.mako
/...
And the _init_.py file will contain the includeme function and will define new routes:
def includeme(config):
config.add_route('route1', '/route1/')
config.add_route('route2', '/route2/')
config.scan()
When i'm writing a view for the worflow_app1, i'm rendering to a template included with that app, but when i'm calling it from the core app, it can't render the template and gives the following error:
TopLevelLookupException: Cant locate template for uri 'workflow-app1.mako'
This error quite logical cause the mako.directories directive is given with the path App_Core_PATH/templates so my template should be in the same folder.
Question1:
Is it possible to make mako searching in each folder of modules the wanted templates?
Question2:
Is it possible to make the workflow-app1.mako inheriting of the base.mako from the core app?
Thanks by advance for your answer.
The solution that I would recommend is switching to asset specs for your templates. They are explicit, allow overriding, and provide better control over your template hierarchy. This means that you would stop using mako.directories and instead use 'workflow_app1:templates/workflow_app1.mako' in your inherits or include or renderer arguments. Given this, it's obvious that you can inherit from your base.mako in your core app, whereas managing the mako.directories option is more difficult.
If you're deadset on mako.directories then you can add a line to it every time you add a package to pyramid.includes.
mako.directores =
App_Core:templates
workflow_app1:templates
workflow_app2:templates
Another option is to switch to jinja2, as its plugin has the ability to add search paths after the fact. Thus your included modules can config.add_jinja2_search_path(...) throwing themselves into the lookup order. Pyramid's mako integration does not offer this option right now.

Issues with M:1 relations using Objectify 1.1rc and CRUD on Play 1.1

I'm having a really odd issue and maybe one of you can shed some light
on it. I would appreciate it :)
I'm developing an application using Objectify 1.1rc module for Play! Framework 1.1. I have 2 related objects whose relevant parts are:
public class User extends ObjectifyModel<User> {
[...]
public List<Key<Theatre>> theatres;
[...]
}
public class Theatre extends ObjectifyModel<Theatre> {
[...]
}
Some background:
I'm using Objectify 1.1rc from the Google code repository (the module in Play repository seems to fail with Play! 1.1) The sample application works fine
I based the objects in existing objects working properly on the sample application provided with the Objectify-1.1rc module for Play Framework (Showcase).
I did debugging and testing by pointing my application and the sample application (Showcase) to the same CRUD module.
I can link them using Java code without any problem.
Presently I have 2 issues that I cannot solve, which are:
M:1 relation not being saved
I have an issue with the 'theatres' relation from the User class. When editing an
object of type User via CRUD, I can see the multi-select control to relate Theatre instances to the User, When I click on some (one or more) of them and save the object, the relation is not saved, making it impossible to link the objects via the CRUD interface.
How can make it work?
CRUD code not being accessed by one application but accessed by the other
The sample application from Objectify module (Showcase) allows me to save M:1 relations using CRUD. As I mentioned before, both my application and showcase point to the same CRUD module, so they should use exactly the same code. What I noticed, by debugging via Log outputs, is that my application uses CRUD, but the sample application uses all the code up to a certain point.
The CRUD module traverses to 'tag/form.html', finds a field of type 'relation' (in both my code and the sample application) but when calling the tag '#{crud.relationField}' something odd happens: my application goes into the tag defined in the CRUD module. The sample application doesn't access that code, no logs added to that tag are triggered (at any point of the file).
I've searched for any replacement of the tag in the sample application, but I'm unable to find one. As you can guess, it's driving em crazy and making me start believing in green leprechauns living in my desktop (without giving me the gold, damn them!)
Anyone knows why does this happen? And were can I find the code being executed by the sample application? Finding it would most likely solve the issue #1
Thanks a lot!
Ok, found the issue to #1. I had a method called "getTheatres()" (should have had another name, was an error) and that was breaking the CRUD. Renaming the method solve issue #1.
I still didn't find why #2 was happening, but I believe I'll leave as one of those "worked in my computer" issues so common in our world...