We have a Web Application Project (dozens actually..) that has a testing project attached to it. In the testing project I have a simple unit test which exercises a couple of methods.
Running locally, the unit test executes and works.
However, when our TFS Build server attempts to execute the test, it fails with a error about an invalid path for the AspNetDevelopmentServerHost attribute. Other team members can execute it just fine.
The problem is that the root of my TFS Workspace is set to c:\projects\ One of the team members has theirs set to c:\tfs2008\ The TFS Build server on the other hand sets the pathToWebRoot variable to "c:\blahblah\Release_PublishedWebsites..." Which results in a bad path.
Due to the number of projects we have, I can't have everyone reset an environment variable every time they switch projects.
So, what are the best practices with regards to unit testing web projects in a team environment? The MSDN site article was in true microsoft fashion less than helpful.
you should specify the string %pathtowebroot%\\WebSiteName in the ,pathToWebApp parameter of the AspNetDevelopmentServer or AspNetDevelopmentServerHost attribute.
We use:
<TestMethod(), _
HostType("ASP.NET"), _
AspNetDevelopmentServerHost("$(SolutionDir)\\MyWebProject", "/"), _
UrlToTest("http://localhost:44444/")>
Public Sub Test()
AssertStuff();
End Sub
The $(SolutionDir) means it works fine in everyone's environment, and all the tests can be checked in. We do have to change it each time we automatically create a new test, but we're writing the test anyway, so it's not too much of a hardship.
It's possible to set environment variables during the build to alter the path and still have it work in a local environment.
How to: Parameterize the URL for a Web Performance Tests Web Server
Testing Web Sites and Web Services in a Team Environment
Related
I have been rushing to get my app, a mixture between nodejs server driving an sqlite database and a litElement based client side providing the ui, into a useable state as a beta release. I achieved that a couple of days ago and now I am (belatedly I know) thinking how to put together a test framework. However I am really struggling to understand how to best test the client side. I think its because I am having difficulty understanding conceptually what the two main choices of framework are. Before I go into more detail, let me explain the structure of the app in top level terms.
At the project root level there are three main directories node_modules which comprises all the modules I've pulled in (including lit-element and web-components-loader which are client side elements - but see below) server which contains all the code for the server side of my application and client which consist of all the code for the client side of my app. I run rollup ONLY at module install time to "package" lit-element and the directives I use and the web-component-loader and effectively treeshake and copy them to the client/libs. As a result of this my client is coded to assume the modules are in the libs directory AND I DO NOT NEED OR HAVE any build stage. I guess the root of the client is index.html which pulls in a service-worker.js and main-app.js. main-app is the root of a tree in lit-element based components that make up the entire client app. Nginx is the web server for all the static files in the client, but also acts as a proxy to pass any urls that start /api to a standard node http web server (not even express, although I do use the router, body-parser and final-handler modules) and these get passed to various api handlers each of which is a separate javascript file - although these can "require" a few common modules that I have written and those in the node_modules directory.
I plan on using jest as a test environment. For my server I think it is easy. For each api handler I want to test I can build a test script that "requires" the javascript file I want to test. I am in two minds about whether to use a sqlite database for testing or mock something - I am leaning towards the former as I am using better-sqlite3 and it is totally synchronous and very fast. I already have scripts to create empty databases, so I have no worry about test isolation.
Client testing is where I get confused. I "think" that in essence jest can run tests the same way as for the server, one element at a time. BUT, these elements and my test scripts are going to need a "web-platform" set of APIs - not least of which is the entire shadow dom and custom components stuff that lit-element uses. This is where, I think, puppeteer or electron in with there associated jest plugins which can put these platform apis into the test environment. But, and this is the essence of my confusion, puppeteer instructions all start with a something like
const browser = await puppeteer.launch({headless: true});
const page = await browser.newPage()
await page.goto(SOME URL);
What is this URL? - do I have to also run a server? I cannot relate this snippet to running a test controlled by jest. All the examples seem to use webpack and typescript, neither of which I know anything about.
The other module I have seen mentioned is electron, in particular this article, which everything else seems to point to (or the same text).
https://www.ninkovic.dev/blog/2020/testing-web-components-with-jest-and-lit-element
From the code snippets in this article it "seems" like it might be what I want, BUT ...
I cannot find very many references to electron other than on its own web site. Here it is telling you to use electron as a tool to build a cross platform application, but nowhere can I find what it is - it assumes you already know. I don't want a UI for my unit testing I want it to be headless like in puppeteer.
Hence my confusion and why I am unsure how to achieve what I want. Can someone give me some pointers as to
How can I set up puppeteer to run headless tests without needing a server OR
What exactly is electron (and can I use it to
a) run my tests
b) provide me with tools to examine the dom elements I have created to see I have created the right ones) and how is it different from puppeteer and can I use it to conduct headless tests of my client.
UPDATE
I've done some more digging and am beginning to understand the differences. Let me summarise what I think I have found.
Puppeteer is great for end to end testing of your site. You run the tests by launching the included puppeteer at the home page of your site (or the more likely scenario of a development test site) and programatically pretend to be a user who can click on buttons etc. You can use various methods, including functions such as document.querySelector() to check your UI has behaved how you think, or you can take screen shots and compare with standardised version. I could possible use it for unit tests, but I would have to run a server, create a test fixture html page for every test and navigate to it. jest-puppeteer is a package with some of that built in.
Electron is a platform for building apps. What the url I was referencing was using a test runner app jest-electron built using electron. So worrying about electron is a red herring, I should be worrying about jest-electron.
My main concern right now, I think, is that I need different jest configurations for my three scenarios
unit tests on the server
unit tests on the client
end to end testing of the complete app.
Given I have only one package.json file and one set of node_modules I need to figure out a way to have three different jest-config.js files.
When developing, my team obviously uses development as our environment.
When we run automated tests, we use testing.
We also have staging and production environments, respectively used for our testers to check out features and the final "live" product.
We're trying to setup an internal CI server to run our automated tests against and to eventually assist with automated deployments.
Since the CI server is really running automated tests, some think it should be run in testing environment. However, in order for the CI server to actually be useful, my thoughts are that it needs to be run in production mode with as close-as-possible a mirror of the actual production environment (without touching the production DB, obviously).
Is there an accepted environment that a CI server should be executed under? production environment (with different DB) seems the only logical answer to me, but I may be missing something...
Running any tests on PROD environment as you said
seems the only logical answer
but is not quite true. There are risks that your tests can seriously damage the actual environment/application to a point where you'll face a recovery option. After all the dark side of testing is to show/find that your software has not only minor bugs and it is working not as expected.
I can think of at least these 'why not test production' considerations:
when the product is launched, the customer rely on it. Expecting that your software is working ()being already tested). Your live environment should do its job and not be loaded with tests. If the product misbehaved (or did not perform), the technical team have to be sent to to cover the damage, fix the gaps and make it run hassle free. Now this not only affected the product cost, but delayed the project deadlines in a major way. This will make a recursive effect at the vendors profits and next few projects.
the production or development team when completes a product development at their end, have to produce this test environment for testing team prior to loading their newly developed product on that environment for testing.
To me, no matter that you
also have staging and production environments
it is essential to use the Test one accordingly. Further more Testing environment should be (configured) as close as it gets to the Production. Also one person could be trying to test while another person breaks the thing that he has been testing. With out the two being separate their is no way to do proper testing.
Just to be full answer, your STAGE environment can have different roles depending on the company.
One is that it can be the QA/STAGE environment that has an exact copy of production which is used for both QA and system testing (testing of the system when a lot of updates/changes or upgrade is going to go into production).
UPDATE:
That was my point too. The QA environment should be a mirror of the PROD. Possible solution about your issue with caching/pre-loading files onto staging/production is creation of pre-/post-steps .bat (let's assume) files.
In our current Test project we use this approach. In pre-steps we set-up files needed for test execution (like removing files from previous runs and downloading latest copies/artifacts). In post-steps we set up reporting files needed.The advantage is that your files will be collected and sync before every execution.
About the
not on the same physical hardware
in my case we support dedicated remote Test server. Advantages are clear, only thing that you need to be considered is that it'll require maintenance (administration).
I have some Web API and some proxy class based on HttpClient for this Web API.
Now I want to have some unit tests that will operate with the proxy class that will interact with Web API.
I have all these three projects organized as one solution in VS 2013. But the problem here that in order to run the tests I have to have Web API project running as well. But if I run Web API I can't run tests. If I run tests, Web API is not started because VS put it down every time when I stop debugging Web API.
Is it possible somehow to keep running Web API while I run unit tests? In a previous VS versions it was possible to keep running web application in IIS express even if you are not debugging it. How to do the same in VS 2013?
For now I've found only one possible solution - open two Visual Studios and run Web API in one of them and tests in another one. But its not convenient and I'm sure there is more elegant solution for the situation...
Use in-memory hosting of your API. That way it will all run in the same process, it will generate zero network traffic and your tests will run much faster.
Other than that, I would always run the Web API in a different VS instance. It is a much more elegant solution in my opinion.
You Can Also start your project with out debugging this will launch an instance of the application but will still allow you to run unit tests.
Start with out Debugging:
1. Right click on the project you want to run.
a. Select set as startup project.
2. Go go the debug menu and click start without debugging.
This will launch an instance of your API and will allow you to test your end points.
In a J2EE web application, how do people manage resources so that they are visible to both the web context and to unit/integration tests?
I find that often you end up having your source/resource folders configured a certain way during development (i.e., what Maven expects) and so your unit tests will run in your IDE. But once the web app is built and packaged into a WAR file (i.e., when your Continuous Integration server has done a build) your unit tests won't run anymore because the resources are located elsewhere.
Do you end up keeping resources in two different places and manually keeping them in sync?
We tried using unit tests in the container but gave up on it years ago. It's much better (for us at least) to make each unit test cover a single class and nothing else, mocking out the dependencies on other classes (see JMock or its many competitors). A good basic rule is that if it touches the database, network, or the filesystem, it isn't a unit test. (It may be useful for something else, but it isn't a unit test. See these unit testing rules for more on this.)
Unit tests written this way can be run anywhere, and they are blazingly fast (we have thousands and run them in under 60 seconds on medium-spec hardware.)
You may also want to run integration tests that check a subsystem or the whole application. We find that subsystem tests can also use mocking at their borders - for instance, we fake an external pricing feed - and that end-to-end tests work best with tools like Selenium or WebDriver, which let you deploy the whole application on a server and then hit it with a browser just like users do.
(By the way, our method of unit testing makes us mockists, rather than classicists, in Martin Fowler's taxonomy.)
Normally this is the reason for multi-module builds. The external services are in a separate build unit than the web application. So you build, package and run your integrations tests when you build that module.
Another module can contain your domain model and its unit tests, which are also run at build time.
It is quite common for a module that results in a WAR to not have any java code in it at all, but only web related artifacts. Although not necessary, this is often done because code that is in a war module cannot be included into another module.
The last special case is the module containing web-tests. This module may often need test-scoped artifacts from the other modules (because it is testing the application from the outside, but may need data from the inside). This can be solves by also packaging test-resources in jar files, creating a separate set of "test" jar files for each modules.
Multi module builds are the norm for maven projects, and are also easy to set up for other build systems like ant.
I won't package testing resources nor tests in a WAR file neither run unit tests from the WAR. Why you are trying to do so?
I'm familiar with TDD and use it in both my workplace and my home-brewed web applications. However, every time I have used TDD in a web application, I have had the luxury of having full access to the web server. That means that I can update the server then run my unit tests directly from the server. My question is, if you are using a third party web host, how do you run your unit tests on them?
You could argue that if your app is designed well and your build process is sound and automated, that running unit tests on your production server isn't necessary, but personally I like the peace of mind in knowing that everything is still "green" after a major update.
For everyone who has responded with "just test before you deploy" and "don't you have a staging server?", I understand where you're coming from. I do have a staging server and a CI process set up. My unit tests do run and I make sure they all pass before an an update to production.
I realize that in a perfect world I wouldn't be concerned with this. But I've seen it happen before. If a file is left out of the update or a SQL script isn't run, the effects are immediately apparent when running your unit tests but can go unnoticed for quite some time without them.
What I'm asking here is if there is any way, if only to satisfy my own compulsive desires, to run a unit test on a server that I cannot install applications on or remote into (e.g. one which I will only have FTP access to in order to update files)?
I think I probably would have to argue that running unit tests on your production server isn't really part of TDD because by the time you deploy to your production environment technically speaking, you're past "development".
I'm quite a stickler for TDD, and when I'm preaching the benefits to clients I often find myself saying "you can't half adopt TDD, it's all or nothing"
What you probably should have is some form of automated testing that you perform "after" deployment but these are not part of TDD.
Maybe you should look at your process again.
You could write functional tests in something like WATIR, WATIN or Selenium that test what is returned in the reponse page after posting certain form data or requesting specific URLs.
For clarification: what sort of access do you have to your web server? FTP or WebDAV only? From your question, I'm guessing ssh access isn't available - you're dropping files in a directory to deploy. Is that correct?
If so, the answer for unit testing is likely 'do it before you deploy'. You can set up functional testing driven by an automated tool like Selenium to test your app remotely via the web interface, but that's not really unit testing the sense that you're restricted to testing the system as a whole.
Have you considered setting up a staging server, perhaps as a VMWare instance, that mirrors or at least mimics your deployment environment?
What's preventing you from running unit tests on the server? If you can upload your production code and let it run there, why can't you upload this other code and run it as well?
I've written test tools for sites using python and httplib/urllib2 generally it would have been overkill but it was suitable in these cases. Not sure it's going to be of general use though.