Insert screenshots in SpecRun/SpecFlow test execution reports

5,209 views
Skip to first unread message

Lévay Szabolcs

unread,
Aug 29, 2013, 10:19:24 AM8/29/13
to spe...@googlegroups.com

I'm using SpecFlow with Selenium WebDriver and SpecRun as test runner to create and execute automated test cases and I'm looking for a solution to insert screenshots in the test execution report.

I wrote a method to create screenshots after every Assert function. The images are saved to a specific location, but when I make the result analysis I have to follow the report and the images as well. It would be nice to have them in the same location (precisely in the report html).

Is there any way to perform this (something similar to Console outputs)?

Thank You!

Gáspár Nagy

unread,
Aug 29, 2013, 11:02:52 AM8/29/13
to spe...@googlegroups.com
Hi,

Yes, this is possible. You have to do the following steps:
1. save the screenshot to the output folder (this is the current working folder where the tests are running).
2. Write out a file line to the console from the test: Console.WriteLine("file:///C:\fullpath-of-the-file.png");
3. Make sure that the generated images are also saved on the build server as artifacts

During the report generation, SpecRun scans the test output for such file URLs and convert them to anchor tags with relative path, so that these will work wherever you distribute your report file (as long as the images are next to it). You can of course tup the images to a subfolder as well.

Br,
Gaspar

Gáspár Nagy

unread,
Aug 29, 2013, 11:05:44 AM8/29/13
to spe...@googlegroups.com
Here is a code snippet that works with Selenium WebDriver. This also saves the HTML source together with the screenshot.

        [AfterScenario]
        public void AfterWebTest()
        {
            if (ScenarioContext.Current.TestError != null)
            {
                TakeScreenshot(cachedWebDriver);
            }
        }

        private void TakeScreenshot(IWebDriver driver)
        {
            try
            {
                string fileNameBase = string.Format("error_{0}_{1}_{2}",
                                                    FeatureContext.Current.FeatureInfo.Title.ToIdentifier(),
                                                    ScenarioContext.Current.ScenarioInfo.Title.ToIdentifier(),
                                                    DateTime.Now.ToString("yyyyMMdd_HHmmss"));

                var artifactDirectory = Path.Combine(Directory.GetCurrentDirectory(), "testresults");
                if (!Directory.Exists(artifactDirectory))
                    Directory.CreateDirectory(artifactDirectory);

                string pageSource = driver.PageSource;
                string sourceFilePath = Path.Combine(artifactDirectory, fileNameBase + "_source.html");
                File.WriteAllText(sourceFilePath, pageSource, Encoding.UTF8);
                Console.WriteLine("Page source: {0}", new Uri(sourceFilePath));

                ITakesScreenshot takesScreenshot = driver as ITakesScreenshot;

                if (takesScreenshot != null)
                {
                    var screenshot = takesScreenshot.GetScreenshot();

                    string screenshotFilePath = Path.Combine(artifactDirectory, fileNameBase + "_screenshot.png");

                    screenshot.SaveAsFile(screenshotFilePath, ImageFormat.Png);

                    Console.WriteLine("Screenshot: {0}", new Uri(screenshotFilePath));
                }
            }
            catch(Exception ex)
            {
                Console.WriteLine("Error while taking screenshot: {0}", ex);

Lévay Szabolcs

unread,
Aug 30, 2013, 3:36:58 AM8/30/13
to spe...@googlegroups.com
Thanks for the quick reply. This is exactly what I need.

Good luck with your further development.

Best Regards,
Szabolcs Levay

jkj2000

unread,
Jan 17, 2014, 8:37:52 PM1/17/14
to spe...@googlegroups.com
We're trying to do the same thing as the OP.

The steps above look like just what we need, but I did have a couple of questions?  Right now we're writing our screenshots out to a 'ScreenShots' subfolder.  Is this allowed or do the screenshots have to be in the output folder for this to work?  Or is it ok as long as we do a console.writeline with the correct screenshot path, even if that path contains the 'ScreenShots' subfolder?

And do we have to write out the PageSource to the console, as in the example above, or is it ok just to do a console.writelines with the screenshot paths?

Is it really just a matter of writing out the screenshot paths to the console, and SpecRun somehow parses the paths and puts the screenshot links in the report?  Sounds great, almost too easy.  Are there any additional steps we need to take?

Thanks much.

Gáspár Nagy

unread,
Jan 20, 2014, 5:47:36 AM1/20/14
to spe...@googlegroups.com
You can do pretty much whatever you want. SpecRun scans the test output for links using the "file://" pattern and if the link is related to an existing file it converts it to relative path (to the generated report) and embeds as a relative HTML link.

This also means that you can use subfolders (we do it often) and you can use this to "link" any related file that might be important for tracing.

In addition to this, if you use TFS, the test adapter that is packaged with SpecRun, besides it can execute the tests and generate the report, it will automatically pick up these files and registers them as test result artifact (so it is kept and accessible from TFS build).

jkj2000

unread,
Jan 22, 2014, 8:16:37 PM1/22/14
to spe...@googlegroups.com
Yes, that worked great for us.  Thanks again.

Just wondering but is the HTML report customizable to any extent?  For instance, we may at some point might want to add links to the error section on our own, using jquery or such.  But the only identifiers I see on there have strange ids such as 't671965005.2' or 't-1903554670.0'.

Do these values relate in some way to the scenarios or features, so that we can embed stuff as needed into the report?

Gáspár Nagy

unread,
Jan 23, 2014, 10:40:27 AM1/23/14
to spe...@googlegroups.com
The link is a hash code generated from the scenario name and all the parent node names. They are only "persistent" as long as you don't rename the titles. I don't know what would be the better strategy for link generation and I'm open to any suggestions.

The HTML report is generated from a razor template, you can get the default template from here: http://go.specflow.org/specrunreporttemplate.

You can override the template using the reportTemplate attribute in the settings node of the profile. With an updated template, you can provide a link generation pattern that better fits to your need.

Br,
Gaspar

jkj2000

unread,
Jan 23, 2014, 5:51:44 PM1/23/14
to spe...@googlegroups.com
Looks good, thanks.  Do you happen to have an example of overriding the reportTemplate attribute, what the node in the profile looks like; where we'd put the new template in the project, etc?

Priti Fhuse

unread,
May 2, 2014, 10:06:21 AM5/2/14
to spe...@googlegroups.com
i m using specflow  for testing 
i wan to attach screen shot for every when and then in html report 

Carlin Scott

unread,
Jun 3, 2015, 8:53:58 PM6/3/15
to spe...@googlegroups.com
My paths aren't showing as links inthe report after following your recommendation below. Is this still working or did the functionality change somehow?

Jordan Jitzchaki

unread,
Apr 29, 2016, 4:30:45 PM4/29/16
to SpecRun
Will the SpecFlow report generator also do this for nunit tests?  I've tried unsuccessfully but not sure if I'm doing something wrong or it just isn't possible.

leo stone

unread,
Jun 22, 2016, 9:59:40 AM6/22/16
to SpecRun
Hi Gáspár,

I am trying to implement your solution but I have some trouble with your third point.

3. Make sure that the generated images are also saved on the build server as artifacts

After days of trying I still have no clue how to do this. Could you give a small example/description of how I would properly publish a generated png to the TFS.

Thank you so much
leo

PS: Maybe I am trying something that is not possible. Please have a look at the picture below.
My goal is, to have the generated screenshot in the "Attachments" List. 
Do you think this is possible with your approach?

TJ

unread,
Nov 7, 2016, 2:51:26 PM11/7/16
to SpecRun
I just ran into similar issues with getting the report generator to recognize my PNGs... I figured that I would post this here in case anyone else is having trouble.

My initial code which output the screenshot URI that was not working:
Console.WriteLine("Screenshot: " + new Uri(screenshotPath));

This is what I had to do to get it working:
Console.WriteLine("Screenshot: " + new Uri(screenshotPath).ToString().Replace(" ", "%20"));

So, as you can see there appears to be an issue with the report generator recognizing URI's that contain spaces.

Franklin Araujo

unread,
Nov 9, 2016, 3:45:06 PM11/9/16
to SpecRun
 [AfterScenario("geralafter")]
        public void TearDown()

        {
             if (ScenarioContext.Current.TestError != null)
            {

                Data.Builders.BemViver.TearDown.TakeScreenshot(Instance);
            }


 public static void TakeScreenshot(IWebDriver driver)
        {
            try
            {
                string fileNameBase = string.Format("error_{0}_{1}_{2}",
                                                    FeatureContext.Current.FeatureInfo.Title.ToIdentifier(),
                                                    ScenarioContext.Current.ScenarioInfo.Title.ToIdentifier(),
                                                    DateTime.Now.ToString("yyyyMMdd_HHmmss"));

                var artifactDirectory = Path.Combine(Directory.GetCurrentDirectory(), "ResultadoTestes");
                if (!Directory.Exists(artifactDirectory))
                    Directory.CreateDirectory(artifactDirectory);

                string pageSource = driver.PageSource;
                string sourceFilePath = Path.Combine(artifactDirectory, fileNameBase + "_source.html");
                File.WriteAllText(sourceFilePath, pageSource, Encoding.UTF8);
                Console.WriteLine("Page source: {0}", new Uri(sourceFilePath));

                ITakesScreenshot takesScreenshot = driver as ITakesScreenshot;

                if (takesScreenshot != null)
                {
                    var screenshot = takesScreenshot.GetScreenshot();

                    string screenshotFilePath = Path.Combine(artifactDirectory, fileNameBase + "_screenshot.png");

                    screenshot.SaveAsFile(screenshotFilePath, ImageFormat.Png);

                    Console.WriteLine("Screenshot: {0}", new Uri(screenshotFilePath));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error while taking screenshot: {0}", ex);
            }
        }

Maksym GO

unread,
Jul 6, 2017, 2:13:52 PM7/6/17
to SpecRun
Hello,

Do you have experience to create screenshot in multithreading run ?
As I can see [BeforeScenario] and [AfterScenario] executes in one main thread, but test executes in other. 
So, when I try to create report with screenshots, all screenshots added to tests that executed in thread #0. No screenshots for other threads. 

Please notify if anybody know how to resolve it. 
SF = 2.1.0
SR = 1.5.2
Reply all
Reply to author
Forward
0 new messages