Baixe o app para aproveitar ainda mais
Prévia do material em texto
Software Testing Software User Software Testing Software User Test Case Study: Factoring Integer Numbers Adapted from: http://homepages.dcc.ufmg.br/~fernando/classes/dcc052/ementa/lesson3/ Objective • Write a class PrimeFactorizer, that, given an integer number, returns an array with all the prime factors of this number. Writing a Unit Test package juTestingEx; import junit.framework.TestCase; public class TestFactors extends TestCase { public TestFactors(String name) { super(name); } public void testEx() throws Exception { int tmp = 2 * 2; assertEquals(4, tmp); } } Writing a Unit Test What are good tests? • Automated and repeatable • Easy to implement • Once written, remain for future use • Run at the push of the button • Orthogonal (non-redundant behavior) A Simple Test Case • What is the simplest test case that our Factorizer should pass? A Simple Test Case public void testTwo() { int factors[] = PrimeFactorizer.factor(2); assertEquals(1, factors.length); assertEquals(2, factors[0]); } We wrote the test without really having the program to be tested. This is called intentional programming. A Simple Program • What is the smallest program that we can create so that our app compiles? A Simple Program package juTestingEx; public class PrimeFactorizer { public static int[] factor(int i) { return null; } } What is the difference between a test error and a test failure? A Simple Program • What is the minimum program that we can write so that our application passes the test? A Simple Program package juTestingEx; public class PrimeFactorizer { public static int[] factor(int i) { return new int[] {2}; } } Checkstyle • Is a development tool to help programmers write Java code that adheres to a coding standard. • Automates the process of checking Java code to spare humans of this boring (but important) task. This makes it ideal for projects that want to enforce a coding standard. • Supports the Sun Code Conventions • Is available at http://checkstyle.sourceforge.net/ Checkstyle ArrayTrailingComma Description Checks that array initialization contains a trailing comma. int[] a = new int[] { 1, 2, 3, }; The check allows to not add a comma if both left and right curlys are on the same line. return new int[] { 0 }; Rationale: Putting this comma in makes it easier to change the order of the elements or add new elements on the end. A Simple Program “style checked” package com.primeFactorizer; /** * This class factorizes a prime number. * @author jefersson * */ public final class PrimeFactorizer { /** * Private constructor to avoid instantiation. */ private PrimeFactorizer() { } /** * This method factors an integer number. * @param i the number to be factored out. * @return an array of integers, where each element is a factor of i. */ public static int[] factor(final int i) { return new int[] {2}; } } A Simple Program “style checked” package com.primeFactorizer; /** * This class factorizes a prime number. * @author jefersson * */ public final class PrimeFactorizer { /** * Private constructor to avoid instantiation. */ private PrimeFactorizer() { } /** * This method factors an integer number. * @param i the number to be factored out. * @return an array of integers, where each element is a factor of i. */ public static int[] factor(final int i) { return new int[] {2}; } } Why? A Simple Program “style checked” package com.primeFactorizer; /** * This class factorizes a prime number. * @author jefersson * */ public final class PrimeFactorizer { /** * Private constructor to avoid instantiation. */ private PrimeFactorizer() { } /** * This method factors an integer number. * @param i the number to be factored out. * @return an array of integers, where each element is a factor of i. */ public static int[] factor(final int i) { return new int[] {2}; } } Why? • Thread safety • Minor compiler optimizations • Documentation A Simple Test Case • What is the simplest test case we can add to this? A Simple Test Case • What is the simplest test case we can add to this? public final void testThree() throws Exception { int[] factors = PrimeFactorizer.factor(3); assertEquals(1, factors.length); assertEquals(3, factors[0]); } A Simple Program • And what is the simplest way to make our program to pass the test? A Simple Program • And what is the simplest way to make our program to pass the test? public static int[] factor(final int i) { if (i == 2) { return new int[] { 2 }; } else { return new int[] { 3 }; } } Refactoring • “Is a controlled technique for improving the design of an existing code base” (M. Fowler, 1999) Some references: http://www.ben-morris.com/why-refactoring-code-is-almost-always-better-than-rewriting-it http://refactoring.com/ Code Refactoring • How could we refactor this code, to make it more general? public static int[] factor(final int i) { return new int[] { i }; } Code Refactoring • How could we refactor this code, to make it more general? public static int[] factor(final int i) { return new int[] { i }; } The name 'i' is not very meaningful. Let's do some more refactoring? Code Refactoring • How could we refactor this code, to make it more general? public static int[] factor(final int multiple) { return new int[] { multiple }; } A New Test • What is the next test that we should add? A New Test • What is the next test that we should add? public static int[] factor(int multiple) { // Compute the new factors: int currentFactor = 0; int[] factorRegister = new int[2]; for (; (multiple % 2) == 0; multiple /= 2) { factorRegister[currentFactor++] = 2; } if (multiple != 1) { factorRegister[currentFactor++] = multiple; } // Trim the array, so that we pass the tests: int[] factors = new int[currentFactor]; for (int i = 0; i < currentFactor; i++) { factors[i] = factorRegister[i]; } return factors; } More Refactoring... • The code is messy. What are the problems? public static int[] factor(int multiple) { // Compute the new factors: int currentFactor = 0; int[] factorRegister = new int[2]; for (; (multiple % 2) == 0; multiple /= 2) { factorRegister[currentFactor++] = 2; } if (multiple != 1) { factorRegister[currentFactor++] = multiple; } // Trim the array, so that we pass the tests: int[] factors = new int[currentFactor]; for (int i = 0; i < currentFactor; i++) { factors[i] = factorRegister[i]; } return factors; } More Refactoring... • The code is messy. What are the problems? publicstatic int[] factor(int multiple) { // Compute the new factors: int currentFactor = 0; int[] factorRegister = new int[2]; for (; (multiple % 2) == 0; multiple /= 2) { factorRegister[currentFactor++] = 2; } if (multiple != 1) { factorRegister[currentFactor++] = multiple; } // Trim the array, so that we pass the tests: int[] factors = new int[currentFactor]; for (int i = 0; i < currentFactor; i++) { factors[i] = factorRegister[i]; } return factors; } Many concepts in the same function! 1. package com.primeFactorizer; 2. 3. import java.util.Vector; 4. public final class PrimeFactorizer { 5. private static int factorIndex; 6. private static int[] factorRegister; 7. private PrimeFactorizer() { } 8. public static int[] factor(int multiple) { 9. initialize(); 10. findPrimeFactors(multiple); 11. return copyToResult(); 12. } 13. private static void initialize() { 14. factorIndex = 0; 15. factorRegister = new int[2]; 16. } 17. private static void findPrimeFactors(final int multiple) { 18. int aux = multiple; 19. for (; (aux % 2) == 0; aux /= 2) { 20. factorRegister[factorIndex++] = 2; 21. } 22. if (aux != 1) { 23. factorRegister[factorIndex++] = aux; 24. } 25. } 26. private static int[] copyToResult() { 27. int[] factors = new int[factorIndex]; 28. for (int i = 0; i < factorIndex; i++) { 29. factors[i] = factorRegister[i]; 30. } 31. return factors; 32. } 33. } A New Test • What is the next test that we should add? A New Test • What is the next test that we should add? public final void testFour() throws Exception { int[] factors = PrimeFactorizer.factor(4); assertEquals(2, factors.length); assertEquals(2, factors[0]); assertEquals(2, factors[1]); } public final void testFive() throws Exception { int[] factors = PrimeFactorizer.factor(5); assertEquals(1, factors.length); assertEquals(5, factors[0]); } A New Test • What is the next test that we should add? public final void testFour() throws Exception { int[] factors = PrimeFactorizer.factor(4); assertEquals(2, factors.length); assertEquals(2, factors[0]); assertEquals(2, factors[1]); } public final void testFive() throws Exception { int[] factors = PrimeFactorizer.factor(5); assertEquals(1, factors.length); assertEquals(5, factors[0]); } Do we have to change the code to pass 4 and 5? 1. package com.primeFactorizer; 2. 3. import java.util.Vector; 4. public final class PrimeFactorizer { 5. private static int factorIndex; 6. private static int[] factorRegister; 7. private PrimeFactorizer() { } 8. public static int[] factor(int multiple) { 9. initialize(); 10. findPrimeFactors(multiple); 11. return copyToResult(); 12. } 13. private static void initialize() { 14. factorIndex = 0; 15. factorRegister = new int[2]; 16. } 17. private static void findPrimeFactors(final int multiple) { 18. int aux = multiple; 19. for (; (aux % 2) == 0; aux /= 2) { 20. factorRegister[factorIndex++] = 2; 21. } 22. if (aux != 1) { 23. factorRegister[factorIndex++] = aux; 24. } 25. } 26. private static int[] copyToResult() { 27. int[] factors = new int[factorIndex]; 28. for (int i = 0; i < factorIndex; i++) { 29. factors[i] = factorRegister[i]; 30. } 31. return factors; 32. } 33. } What is the next test case that will fail? A New Test • How to make it pass testEight? public final void testEight() throws Exception { int[] factors = PrimeFactorizer.factor(8); assertEquals(3, factors.length); assertEquals(2, factors[0]); assertEquals(2, factors[1]); assertEquals(2, factors[2]); } 1. We must increase the size of the array of factors, but, which size to use? A New Test • How to make it pass testEight? public final void testEight() throws Exception { int[] factors = PrimeFactorizer.factor(8); assertEquals(3, factors.length); assertEquals(2, factors[0]); assertEquals(2, factors[1]); assertEquals(2, factors[2]); } 1. We must increase the size of the array of factors, but, which size to use? 2. What is the largest number of factors an integer can have? A New Test • How to make it pass testEight? public final void testEight() throws Exception { int[] factors = PrimeFactorizer.factor(8); assertEquals(3, factors.length); assertEquals(2, factors[0]); assertEquals(2, factors[1]); assertEquals(2, factors[2]); } 1. We must increase the size of the array of factors, but, which size to use? 2. What is the largest number of factors an integer can have? 3. What is the largest integer that we can handle? A New Test • How to make it pass testEight? public static final int MAX_NUM_FACTORS = 64; private static void initialize() { factorIndex = 0; factorRegister = new int[MAX_NUM_FACTORS]; } 1. package com.primeFactorizer; 2. 3. import java.util.Vector; 4. public final class PrimeFactorizer { 5. private static int factorIndex; 6. private static int[] factorRegister; 7. public static final int MAX_NUM_FACTORS = 64; 8. private PrimeFactorizer() { } 9. public static int[] factor(int multiple) { 10. initialize(); 11. findPrimeFactors(multiple); 12. return copyToResult(); 13. } 14. private static void initialize() { 15. factorIndex = 0; 16. factorRegister = new int[MAX_NUM_FACTORS]; 17. } 18. private static void findPrimeFactors(final int multiple) { 19. int aux = multiple; 20. for (; (aux % 2) == 0; aux /= 2) { 21. factorRegister[factorIndex++] = 2; 22. } 23. if (aux != 1) { 24. factorRegister[factorIndex++] = aux; 25. } 26. } 27. private static int[] copyToResult() { 28. int[] factors = new int[factorIndex]; 29. for (int i = 0; i < factorIndex; i++) { 30. factors[i] = factorRegister[i]; 31. } 32. return factors; 33. } 34. } What is the next test case that will fail? A New Test • How to make it pass testNine? public final void testNine() throws Exception { int[] factors = PrimeFactorizer.factor(9); assertEquals(2, factors.length); assertEquals(3, factors[0]); assertEquals(3, factors[1]); } • How this would extends to 25? A New Test • How to make it pass testNine? public final void testNine() throws Exception { int[] factors = PrimeFactorizer.factor(9); assertEquals(2, factors.length); assertEquals(3, factors[0]); assertEquals(3, factors[1]); } • How this would extends to 25? Refactoring... • Can you see the loop pattern? private static void findPrimeFactors(final int multiple){ int aux = multiple; for (int factor = 2; aux != 1; factor++) { for (; (aux % factor) == 0; aux /= factor) { factorRegister[factorIndex++] = factor; } } } Javadoc Adapted from: http://homepages.dcc.ufmg.br/~fernando/classes/dcc052/ementa/lesson3/ Comments Comments /** * This class factorizes a prime number. * @author jefersson * */ public final class PrimeFactorizer { // ERROAQUI! for (int factor = 2; aux != 1; factor++) { for (; (aux % factor) == 0; aux /= factor) { factorRegister[factorIndex++] = factor; } } How to Write Doc Comments for the Javadoc Tool: http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html
Compartilhar