\documentclass[10pt,a4paper]{article} % Packages \usepackage{fancyhdr} % For header and footer \usepackage{multicol} % Allows multicols in tables \usepackage{tabularx} % Intelligent column widths \usepackage{tabulary} % Used in header and footer \usepackage{hhline} % Border under tables \usepackage{graphicx} % For images \usepackage{xcolor} % For hex colours %\usepackage[utf8x]{inputenc} % For unicode character support \usepackage[T1]{fontenc} % Without this we get weird character replacements \usepackage{colortbl} % For coloured tables \usepackage{setspace} % For line height \usepackage{lastpage} % Needed for total page number \usepackage{seqsplit} % Splits long words. %\usepackage{opensans} % Can't make this work so far. Shame. Would be lovely. \usepackage[normalem]{ulem} % For underlining links % Most of the following are not required for the majority % of cheat sheets but are needed for some symbol support. \usepackage{amsmath} % Symbols \usepackage{MnSymbol} % Symbols \usepackage{wasysym} % Symbols %\usepackage[english,german,french,spanish,italian]{babel} % Languages % Document Info \author{Sérgio Ferreira (AlienEngineer)} \pdfinfo{ /Title (c-unit-tests-basics.pdf) /Creator (Cheatography) /Author (Sérgio Ferreira (AlienEngineer)) /Subject (C\# Unit-Tests - Basics Cheat Sheet) } % Lengths and widths \addtolength{\textwidth}{6cm} \addtolength{\textheight}{-1cm} \addtolength{\hoffset}{-3cm} \addtolength{\voffset}{-2cm} \setlength{\tabcolsep}{0.2cm} % Space between columns \setlength{\headsep}{-12pt} % Reduce space between header and content \setlength{\headheight}{85pt} % If less, LaTeX automatically increases it \renewcommand{\footrulewidth}{0pt} % Remove footer line \renewcommand{\headrulewidth}{0pt} % Remove header line \renewcommand{\seqinsert}{\ifmmode\allowbreak\else\-\fi} % Hyphens in seqsplit % This two commands together give roughly % the right line height in the tables \renewcommand{\arraystretch}{1.3} \onehalfspacing % Commands \newcommand{\SetRowColor}[1]{\noalign{\gdef\RowColorName{#1}}\rowcolor{\RowColorName}} % Shortcut for row colour \newcommand{\mymulticolumn}[3]{\multicolumn{#1}{>{\columncolor{\RowColorName}}#2}{#3}} % For coloured multi-cols \newcolumntype{x}[1]{>{\raggedright}p{#1}} % New column types for ragged-right paragraph columns \newcommand{\tn}{\tabularnewline} % Required as custom column type in use % Font and Colours \definecolor{HeadBackground}{HTML}{333333} \definecolor{FootBackground}{HTML}{666666} \definecolor{TextColor}{HTML}{333333} \definecolor{DarkBackground}{HTML}{2E60A3} \definecolor{LightBackground}{HTML}{F1F5F9} \renewcommand{\familydefault}{\sfdefault} \color{TextColor} % Header and Footer \pagestyle{fancy} \fancyhead{} % Set header to blank \fancyfoot{} % Set footer to blank \fancyhead[L]{ \noindent \begin{multicols}{3} \begin{tabulary}{5.8cm}{C} \SetRowColor{DarkBackground} \vspace{-7pt} {\parbox{\dimexpr\textwidth-2\fboxsep\relax}{\noindent \hspace*{-6pt}\includegraphics[width=5.8cm]{/web/www.cheatography.com/public/images/cheatography_logo.pdf}} } \end{tabulary} \columnbreak \begin{tabulary}{11cm}{L} \vspace{-2pt}\large{\bf{\textcolor{DarkBackground}{\textrm{C\# Unit-Tests - Basics Cheat Sheet}}}} \\ \normalsize{by \textcolor{DarkBackground}{Sérgio Ferreira (AlienEngineer)} via \textcolor{DarkBackground}{\uline{cheatography.com/89520/cs/20379/}}} \end{tabulary} \end{multicols}} \fancyfoot[L]{ \footnotesize \noindent \begin{multicols}{3} \begin{tabulary}{5.8cm}{LL} \SetRowColor{FootBackground} \mymulticolumn{2}{p{5.377cm}}{\bf\textcolor{white}{Cheatographer}} \\ \vspace{-2pt}Sérgio Ferreira (AlienEngineer) \\ \uline{cheatography.com/alienengineer} \\ \end{tabulary} \vfill \columnbreak \begin{tabulary}{5.8cm}{L} \SetRowColor{FootBackground} \mymulticolumn{1}{p{5.377cm}}{\bf\textcolor{white}{Cheat Sheet}} \\ \vspace{-2pt}Published 28th August, 2019.\\ Updated 3rd September, 2019.\\ Page {\thepage} of \pageref{LastPage}. \end{tabulary} \vfill \columnbreak \begin{tabulary}{5.8cm}{L} \SetRowColor{FootBackground} \mymulticolumn{1}{p{5.377cm}}{\bf\textcolor{white}{Sponsor}} \\ \SetRowColor{white} \vspace{-5pt} %\includegraphics[width=48px,height=48px]{dave.jpeg} Measure your website readability!\\ www.readability-score.com \end{tabulary} \end{multicols}} \begin{document} \raggedright \raggedcolumns % Set font size to small. Switch to any value % from this page to resize cheat sheet text: % www.emerson.emory.edu/services/latex/latex_169.html \footnotesize % Small font. \begin{multicols*}{2} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{\{\{fa-thumbs-up\}\} Arrange - Act - Assert}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{public void MyTest() \{ \newline // Arrange - Only setup code needed by the act step\{\{nl\}\} \newline // Act - Only the action(s) under test\{\{nl\}\} \newline // Assert - Verification of the excepted behavior \newline \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{{\bf{Tip}}: If any of these parts are greatly bigger than the others, look for refactoring your tests.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{\{\{fa-thumbs-up\}\} Test Class Organization}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{class SubjectTests \{ \newline \newline // fields \newline int callCount = 0; \newline \newline // help methods \newline private Subject MakeSubject() =\textgreater{} \newline new Subject(); \newline \newline // test methods \newline public void Test1() \{ \} \newline public void Test2() \{ \} \newline public void Test3() \{ \} \newline \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{This is just a convention. Don't leave help methods and field scattered all around the test methods.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{\{\{fa-info-circle\}\} Solitary vs Sociable}} \tn % Row 0 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{{\bf{Solitary}} \{\{nl\}\} Type of test that tests a unit without the involvement of other units. \{\{nl\}\} {\emph{Mocks all dependencies of the subject under test.}}} \tn % Row Count 3 (+ 3) % Row 1 \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{{\bf{Sociable}} \{\{nl\}\} Type of test that uses multiple units to verify a given behavior. \{\{nl\}\} {\emph{Mock only hard to manage dependencies. (e.g. external resources)}}} \tn % Row Count 7 (+ 4) \hhline{>{\arrayrulecolor{DarkBackground}}-} \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{source: Working Effectively with Unit Tests by Jay Fields} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Column Break \#1}} \tn % Row 0 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{} \tn % Row Count 0 (+ 0) \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{\{\{fa-question\}\} Unit-Test}} \tn % Row 0 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{We have control over all it's parts.} \tn % Row Count 1 (+ 1) % Row 1 \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{Runs in any order.} \tn % Row Count 2 (+ 1) % Row 2 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{Doesn't depend on another test.} \tn % Row Count 3 (+ 1) % Row 3 \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{Doesn't produce side-effects.} \tn % Row Count 4 (+ 1) % Row 4 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{Asserts observable behavior.} \tn % Row Count 5 (+ 1) \hhline{>{\arrayrulecolor{DarkBackground}}-} \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{{\bf{Tip}}: if any of these is false then it's not a unit-test.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{\{\{fa-info-circle\}\} Test - What's your name?}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{// Convention \#1 \newline public void \seqsplit{Creating\_a\_user\_stores\_it\_in\_the\_database()} \{ ... \} \newline public void \seqsplit{Creating\_a\_user\_without\_name\_throws\_exception()} \{ ... \} \newline \newline \newline // Convention \#2 \newline public void \seqsplit{CreateUser\_StoresInDatabase()} \{ ... \} \newline public void \seqsplit{CreateUser\_WithoutName\_ThrowsException()} \{ ... \} \newline \newline \newline // Convention \#3 \newline public void \seqsplit{Given\_user\_when\_creating\_then\_its\_stored\_in\_database()} \{ ... \} \newline public void \seqsplit{Given\_user\_when\_has\_no\_name\_then\_throws\_exception()} \{ ... \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{The name of the test should have 3 parts: \newline ~~- The behavior under test; \newline ~~- The constraints; \newline ~~- The expected behavior.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{\{\{fa-bolt\}\} Actions on Loops}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{public void Test1() \{ \newline for(var x in listOfInt) \{ \newline Assert.That(GetValue(x), Is.True)); \newline \} \newline \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{{\bf{Tip}}: Multiple asserts and action taken within a loop on the same test makes us ignore some cases in case of a failure.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Page break \#1}} \tn % Row 0 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{} \tn % Row Count 0 (+ 0) \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{\{\{fa-bolt\}\} Avoid some Expectations}} \tn % Row 0 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{// Thats how it's done\{\{nl\}\}`mock.Verify(...)`} \tn % Row Count 1 (+ 1) % Row 1 \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{// If possible use specific value, is int.MaxValue a valid expectation?\{\{nl\}\}`Assert.That(x, Is.GreaterThan(10))`} \tn % Row Count 4 (+ 3) % Row 2 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{// Might be null\{\{nl\}\}`var result = GetObject();`\{\{nl\}\}`Assert.That(result.Property, Is.True))`} \tn % Row Count 6 (+ 2) % Row 3 \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{// Might throw exception somewhere other than action\{\{nl\}\}`{[}ExpectException(){]}`} \tn % Row Count 8 (+ 2) % Row 4 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{// Look for content not types \{\{nl\}\} \seqsplit{`Assert.IsInstanceOfType(result}, typeof(SomeDataModel));`} \tn % Row Count 10 (+ 2) \hhline{>{\arrayrulecolor{DarkBackground}}-} \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{{\bf{Avoid}} != {\bf{Never do it}}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{x{4 cm} x{4 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{8.4cm}}{\bf\textcolor{white}{\{\{fa-info-circle\}\} Don't ignore the signs!}} \tn % Row 0 \SetRowColor{LightBackground} {\bf{Sign}} & {\bf{Outcome}} \tn % Row Count 1 (+ 1) % Row 1 \SetRowColor{white} A big arrange section: large dto, many parameters or many mocks. & Subject under test might be doing to much. \tn % Row Count 5 (+ 4) % Row 2 \SetRowColor{LightBackground} Tests to data model object (dto). & Reveals missing tests. DTOs will get their coverage from usage. \tn % Row Count 9 (+ 4) % Row 3 \SetRowColor{white} Tests to Exceptions. & Reveals missing tests. Exceptions will be tested by their usage. \tn % Row Count 13 (+ 4) % Row 4 \SetRowColor{LightBackground} Big test file & Can indicate duplication or the subject under test is doing to much. \tn % Row Count 17 (+ 4) % Row 5 \SetRowColor{white} Json, xml, etc & Formatted strings of any kind reveal coupling. {\emph{Except tests to formatters.}} \tn % Row Count 21 (+ 4) \hhline{>{\arrayrulecolor{DarkBackground}}--} \SetRowColor{LightBackground} \mymulticolumn{2}{x{8.4cm}}{{\bf{Big file}} : Any file greater than 500 lines \newline {\bf{Big section}} : More than 10 lines. \newline {\bf{Many parameters}} : More than 3. \newline {\bf{Many Mocks}} : More than 3. \newline {\bf{Large dto}}: More than 10 properties.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{\{\{fa-thumbs-up\}\} Parameterized (NUnit)}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{{[}Test{]} \newline public void Test1({[}Values(1, 2, 3){]} int value) \{ \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Column Break \#2}} \tn % Row 0 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{} \tn % Row Count 0 (+ 0) \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{\{\{fa-thumbs-up\}\} Parameterized (xUnit)}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{{[}Theory{]} \newline {[}InlineData(1){]} \newline {[}InlineData(2){]} \newline {[}InlineData(3){]} \newline public void Test1(int value) \{ \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{\{\{fa-thumbs-up\}\} Parameterized (MS Tests v2)}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{{[}DataTestMethod{]} \newline {[}DataRow(1){]} \newline {[}DataRow(2){]} \newline {[}DataRow(3){]} \newline public void Test1(int value) \{ \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{\{\{fa-bolt\}\} Isolate - Shared data}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{static int value = 0; \newline \newline public void Test1() \{ \newline value = 10; \newline doSomething(value); \newline \} \newline \newline public void Test2() \{ \newline doSomething(value); \newline \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{Static mutable state will eventually kill one or more tests.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{\{\{fa-bolt\}\} Isolation - Thread safe tests}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{static object lockObject = new object(); \newline \newline public void Test1() \{ \newline lock(lockObject) \{ \newline // thread safe code \newline \} \newline \} \newline \newline public void Test2() \{ \newline lock(lockObject) \{ \newline // thread safe code \newline \} \newline \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{Avoid this! Dealing with thread safety in tests adds another layer of complexity.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} % That's all folks \end{multicols*} \end{document}