Continuous Integration For .Net and Javascript with Unit tests - asp.net

I need a Continuous integration tool that will support both .Net Unit tests and Javascript unit tests and perform the builds.
It looks like my main options are CruiseControl.NET using JUnit and NUnit or Team City and JS Test Driver.
Are there any other options and which ones have you used or had good or bad experiences with.
thanks

+1 for CC.Net here. I use a combination of CC.Net and NUnit & Selenium for UI testing. CC.Net allows you to do everything you require and it's a doddle to setup.
You can write custom modules to allow you to do things such as incremenet build numbers and modify config files on the build server.
You can happily use a combination of unit tests and Selenium to test the UI using a test such as the following:
[TestFixture]
public class UITest
{
private ISelenium selenium;
private StringBuilder verificationErrors;
[SetUp]
public void SetupTest()
{
selenium = new DefaultSelenium("server", 4444, "*iexplore", "http://server/");
selenium.Start();
verificationErrors = new StringBuilder();
}
[Test]
public void TheUITest()
{
selenium.Open("/RecipeProfessor2/");
selenium.Click("btnTest");
selenium.Click("Button1");
selenium.Click("ctl00_ctl06_toolBar_Home_Solve");
selenium.Click("ctl00_ContentPlaceHolder1_chkIsLive");
selenium.WaitForPageToLoad("30000");
// etc
}
}
You can obviously add in as many tests you require for either standard unit tests or UI tests.

How about something like:
http://www.niltzdesigns.com/blog/2011/04/08/adding-javascript-unit-tests-to-your-continuous-integration-scripts/

Related

Xamarin Forms: Open downloaded file in default Android/iOS application

I am using Xamarin Forms. I would like to download jpg file (it is done) and then open that jpg in default application on Android/iOS (opening photo browser with this photo). Of course photo is single example, I would like to open any file in default application.
I found several solutions native-only but my application is designed to be cross-platform. I though that I can use Launcher from Xamarin.Essentials package but apparently I can't.
How to achieve this?
You can have a try with Xamarin.Essentials: Launcher:
var fn = "File.txt";
var file = Path.Combine(FileSystem.CacheDirectory, fn);
File.WriteAllText(file, "Hello World");
await Launcher.OpenAsync(new OpenFileRequest
{
File = new ReadOnlyFile(file)
});
I found several solutions native-only
Opening something in another app is quite close to the system for a mobile application and there are some things to consider, which dependend on the platform. Usually, mobile apps run in a sandbox with very limited access to the surrounding system. Particularly this means that, if you downloaded a file to the sandbox of your app, other apps (which native viewers are), aren't allowed to access the file.
On Android, you can copy the file to a shared space (see Application.Context.GetExternalFilesDir(null)) and then open it. This might be possible with Essentials, but I'm not quite sure, but since we're on the Android platform anyway now, you could create an intent now anyway.
On iOS you create controllers from within your app (for example the QLPreviewController to preview the file) that may access items in your sandbox. Depending on the type of controller (e.g. UIActivityViewController) they may open other apps.
How to use this platform-independently?
Since you are programming a platform independent app, you'll have to take care that the correct class is called to the platform dependent work. There are several options how you can achieve this
Use the DependencyService
Use a real dependency injection framework
Use an abstract base class with initialization in the platform dependent projects
DependencyService
To use the Xamarin.Forms DependencyService you need two things
An interface for the functionality you'd like to implement
One implementation per platform
Assuming you hvae a simple interface to share a file
public IShareFile
{
void ShareFile(string fileName);
}
you can implement an implementation of this interface on each platform and add the DependencyAttribute to the assembly. e.g. for iOS:
[assembly: Dependency(typeof(MyApp.iOS.DeviceOrientationService))]
namespace MyApp.iOS
{
public class ShareFile : IShareFile
{
public void Share(string fileName)
{
// implementation goes here
}
}
}
The general scaffold is the same for Android, albeit the implementation differs.
Using a real dependency injection framework
Basically it's pretty much the same. You can skip the DependencyAttribute, though. In order to make the implementation available you'll have to get hold of the DI container from your platform specific code, which might be tricky. This might be an overshoot for a single dependency, but if you're using a DI container anyway and there are X dependencies, it might be worth the effort.
Using an abstract base class
Add an abstract base class to your project
public abstract class ShareFile
{
public static ShareFile Instance { get; protected set; }
public abstract void Share(string fileName);
}
and in your implementation in the platform specific project, you add an Init() method
internal class ShareFileImpl : ShareFile
{
public static void Init()
{
ShareFile.Instance = new ShareFileImpl();
}
public void Share(string fileName)
{
// implementation goes here
}
}
This init method must be called from your platform specific code. Most likely during initialization. The implementation can then be accessed via its abstraction from your platform independent code (of course you'll see only the abstraction, public methods added to ShareFileImpl won't be visible from your platform independent code).
ShareFile.Instance.Share(fileName);
A combination of the abstract class approach and dependency injection is also conceivable. When registering your classes in the DI framework, you could register the platform instance like
container.RegisterInstance<ShareFile>(ShareFile.Instance);
This way you can make use of the DI container features (e.g. constructor injection), while keeping the hassles of using the DI container from your platform specific project away from you. The drawback is, that you'll still have to call ShareFileImpl.Init() from your platform specfic code.

VSTS Visual Studio Set Environment Variable Test Project

I am building Integration tests in Visual Studio (2017) for Net Core applications built on VSTS and deployed from there. My projects are test projects, and right now my connection strings to the deployed API url, and the database are hardcoded, but I want to remove them from the code and place them in a VSTS build step that adds environment variables.
Right now, my Test .cs files look something like this:
[TestClass]
public class TestFeature
{
//Set up variables
private static string _connectionString = "server=localhost;port=5432;database=databaseName;user id=postgres;password=postgres";
[TestInitialize]
public void Initialize()
{
}
//And going into my test methods
}
How do I set up my project to read Environment Variables set from the Configuration on VSTS?
What research has dug up for me so far, is to Right Click on Properties of the test project, under Debug, set up Environment Variables with a key and value there.
Then I change my test project to take the GetEnvironmentVariable()
private static string _connectionString = Environment.GetEnvironmentVariable(nameOfVariable);
On the other side in VSTS, I'm trying to find a build step that will set the variable to be the connection string there. The best step I could find is "Set Variable".
However, this is not working for me. The program will not recognize the name of the new variable set in Environment Variables, to start.
You need to add your VSTS variables in the Variables tab.
Another option is to use Powershell to set them if you want to do it in a dynamic fashion using a Powershell script task.
Write-Host "##vso[task.setvariable variable=sauce]crushed tomatoes"
https://learn.microsoft.com/en-us/vsts/build-release/concepts/definitions/release/variables?tabs=powershell
The better way is building, deploying and testing together in a build definition, after the build succeed, then the pull request can be approved.
For this way, you can use the variable in current build (can add/update variable as Marcote said)
If you must do integration test in a separate build, you can set Trigger to Manual in Build validation of Pull Request policy, then you can queue build manually and specify variables’ values (Check Settable at queue time for the variables in build definition)

ExpectedException in xUnit for Legacy Code

As widely stated in other posts, ExpectedException does not exist in xUnit. However, is there something that exists to assist in porting legacy tests to xUnit as essentially a polyfill?
I believe that with an accelerated adoption of .Net Core as we will likely see with .Net Standard 2, we will see more and more tests getting ported from other frameworks to those supported most easily out of the box in .Net Core tooling. While ExpectedException is probably not best practice going forward, having a legacy stopgap (even as e.g. a separate NuGet package) would greatly ease porting tests as this is one of the few transformations that is on a per-test basis and cannot be done by a simple search-replace. And when you're porting hundreds of unit tests, the "this can cause problems" doesn't seem like such a satisfying answer.
I may have misunderstood your question, but you can test for exceptions in xUnit by doing something like this:
[Fact]
public void ExceptionTest()
{
// Arrange
// Act
Action act = () => throw new Exception();
// Assert
Assert.Throws<Exception>(act);
}
Allowing each ExpectedException test to be converted by adding in the xUnit Assert.Throws.

automating asp.net testing

I have to test almost 20 asp.net web application everyday morning to ensure there is no issue in the web sites. so is ther any option to automate it ? There is data entry involved like entering username,password etc.
Note: I will not have the access to the code(only to the applicaiton URL).
Please suggest some option for this, so that we can avoid the manual effort involved in this. Thanks.
Regards,
Jebli.
You should look into web automation tools like WatiN or Selenium.
From the WatiN documentation:
[Test]
public void SearchForWatiNOnGoogle()
{
using (var browser = new IE("http://www.google.com"))
{
browser.TextField(Find.ByName("q")).TypeText("WatiN");
browser.Button(Find.ByName("btnG")).Click();
Assert.IsTrue(browser.ContainsText("WatiN"));
}
}
From the Selenium Documentation:
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium;
class GoogleSuggest
{
static void Main(string[] args)
{
IWebDriver driver = new FirefoxDriver();
//Notice navigation is slightly different than the Java version
//This is because 'get' is a keyword in C#
driver.Navigate().GoToUrl("http://www.google.com/");
IWebElement query = driver.FindElement(By.Name("q"));
query.SendKeys("Cheese");
System.Console.WriteLine("Page title is: " + driver.Title);
driver.Quit();
}
}
WatiN and Selenium are Open Source
VSTT 2010 is a good bet.
Example demos
How To: Functional Testing Automation Using Visual Studio 2010 - http://blogs.msdn.com/b/syedab/archive/2010/01/13/how-to-functional-testing-automation-using-visual-studio-2010.aspx
Data Driving Coded UI Tests - http://blogs.msdn.com/b/mathew_aniyan/archive/2009/03/17/data-driving-coded-ui-tests.aspx

How to do mocks for Web tests?

I want to write a few web tests (over WatiN/Selenium + CassiniDev web server) for my asp.net web application.
Problem I encountered is that I dont know what to do in such situations:
there is a page where user can click the button to call some third-party service. In my web test i want to create mock of this service, which will always return static value (some value in these test case and other value in other test case).
How can i do that?
Currently i use IoC/DI container Microsoft Unity. And my pages gets his dependencies in a manner described in http://msdn.microsoft.com/en-us/library/ff664622%28v=pandp.50%29.aspx.
The only solution that comes to my head is: place all dependencies in web.config for each test case and copy necessary web.config on SetUp of test. This solution completly painful!
Any ideas?
I use WatiN and Cassini-dev in my integration tests as well and have had to deal with similar issues. In my setup fixture I deploy my Asp.Net web application to a temporary folder in my test folder which allows me to play around with the configuration before starting up cassini-dev. I use Windsor for my CI which allows me to change injected components at the configuration level. You may also be able to acheive this with Unity.
If the service you are referring to is a web service you just mock out a web service using the interface you have been coding to.
Here are the steps that I take when running my integration tests:
Create a temp web directory
Publish the Asp.Net web application to the temp directory (I use MSBuild to do this)
Deploy temp database (Using MSbuild and database projects but could be done a number of ways)
Deploy temp membership database (see my blog post on how to do this in code)
Update the web.config of the deployed Asp.Net web application to point to the temp databases and change any other settings relevant for testing.
Start up the website using Cassini-Dev. I also hit the site with a http request so that I can verify the site is up before running any tests.
Run the tests.
After running the tests you should clean up.
Stop cassini-dev
Delete the temp hosting folder
Delete the temp databases. I use Sql server SMO objects that allow me to query the Sql Server which I use to delete up any old databases that have been left lying around after any previously failed test runs.
How to deploy a website using MSbuild in code
var properties = new Dictionary<string, string>
{
{"Configuration", isDebug ? "Debug" : "Release"},
{"WebProjectOutputDir", tempHostingDirectory.FullName},
{"DeployToDatabase", "true"},
{"OutDir", Path.Combine(tempHostingDirectory.FullName, "bin\\")}
};
using (var engine = new ProjectCollection(properties))
{
engine
.LoadProject(<web project path>, "4.0")
.Build(new[] {"Build", "ResolveReferences", "_CopyWebApplication"});
}
Unity configuration section usage: http://www.pnpguidance.net/Post/UnityContainerUnityConfigurationSectionAppConfigWebConfig.aspx
Generating asp.net membership database in code: http://bronumski.blogspot.com/2011/06/generating-creating-aspnet-application.html
Msbuild ProjectCollection on MSDN: http://msdn.microsoft.com/en-us/library/microsoft.build.evaluation.projectcollection.aspx
It sounds like you are trying to mock a web service.
Web services usually inherit from MarshalByRefObject, this means you can create a mock by inheriting from RealProxy to create a transparent proxy that pretends to be the webservice:
class Mock : RealProxy
{
public Mock()
: base(typeof(IStuff)) { }
public IStuff GetStuff()
{
return (IStuff)GetTransparentProxy();
}
public override IMessage Invoke(IMessage msg)
{
IMethodCallMessage message = (IMethodCallMessage)msg;
// the message object provides the MethodInfo that was called
// as well as the arguments.
// <Insert logic here>
return new ReturnMessage(new NotImplementedException("comming soon to a test near you ..."), message);
}
}
I belieave NMock2 uses RealProxy for it's mocks, so you should be able to use it to mock the web service instead.

Resources